Is it possible to programmatically get the ProductName of a Silverlight application? I'm looking for the Silverlight equivalent of this WinForms/WPF instruction:
string productName = System.Windows.Forms.Application.ProductName;
Thank you
You can use the following method, but only if you can guarantee that you call it from the "entry" assembly.
public static void GetProductAndVersionEasy(out string productName, out Version productVersion)
{
var callingAssembly = Assembly.GetCallingAssembly();
// Get the product name from the AssemblyProductAttribute.
// Usually defined in AssemblyInfo.cs as: [assembly: AssemblyProduct("Hello World Product")]
var assemblyProductAttribute = ((AssemblyProductAttribute[])callingAssembly.GetCustomAttributes(typeof(AssemblyProductAttribute),false)).Single();
productName = assemblyProductAttribute.Product;
// Get the product version from the assembly by using its AssemblyName.
productVersion = new AssemblyName(callingAssembly.FullName).Version;
}
(You can replace GetCallingAssembly with GetExecutingAssembly if the method is in your entry assembly).
I also figured out how to hack this information from the .xap file. I load the main assembly's bytes into memory, then read the product and version info from the last few bytes. I had to write this because I needed a method I could reuse in a base library which can be called from anywhere (ie. not the executing or calling assembly).
public static void GetProductAndVersionHack(
out string productName,
out Version productVersion)
{
// Get the name of the entry assembly
var deployment = System.Windows.Deployment.Current;
var entryPointAssembly = deployment.EntryPointAssembly + ".dll";
// Get the assembly stream from the xap file
StreamResourceInfo streamResourceInfo = Application.GetResourceStream(
new Uri(
entryPointAssembly,
UriKind.Relative));
Stream stream = streamResourceInfo.Stream;
// The VERSION_INFO struct as at the end of the file. Just read the last 1000 bytes or so from the stream
// (Keep in mind that there are a lot of zeroes padded at the end of the stream. You should probably
// search for the real stream.Length after trimming them off)
stream.Position = stream.Length - 1000;
StreamReader streamReader = new StreamReader(stream, Encoding.Unicode);
string text = streamReader.ReadToEnd();
// Split the string on the NULL character
string[] strings = text.Split(
new[] { '\0' },
System.StringSplitOptions.RemoveEmptyEntries);
// Get the Product Name (starts with unicode character \u0001)
int ixProductName = strings.FindIndexOf(line => line.EndsWith("\u0001ProductName"));
productName = ixProductName >= 0 ? strings[ixProductName + 1] : null;
// Get the Product Version
int ixProductVersion = strings.FindIndexOf(line => line.EndsWith("\u0001ProductVersion"));
productVersion = ixProductVersion >= 0 ? Version.Parse(strings[ixProductVersion + 1]) : null;
}
public static int FindIndexOf<T>(
this IEnumerable<T> source,
Func<T, bool> match)
{
int i = -1;
foreach (var item in source)
{
++i;
if (match(item)) return i;
}
return -1;
}
Not sure what device your deving for, but for WP7 silverlight, In the Properties folder contained a file called WMAppManifest.xml, and under Deployment>App their is a field called Title, you can pull the XML out of there?
I hope that helps.
The AssemblyName class provides parsing of the Assembly FullName property.
Try this
string productName = (new System.Reflection.AssemblyName(this.GetType().Assembly.FullName)).Name;
Related
We want to compress a big string in our DynamoDB table, which is a JSON object.
I want to simply replace it with a compressed string. I looked into DynamoDB documentation, which uses ByteBuffer to be stored directly, as mentioned here.
But since I don't want to save ByteArray, and instead store a compressed string version of the original string, I have modified it.
Here is what I've done:
public class GZIPStringCompression {
public static String compress(String data) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(data.length());
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
gzipOutputStream.write(data.getBytes());
gzipOutputStream.close();
return byteArrayOutputStream.toString();
}
public static String decompress(String compressed) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(compressed.getBytes());
GZIPInputStream gis = new GZIPInputStream(bis);
BufferedReader br = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
gis.close();
bis.close();
return sb.toString();
}
}
This gives out the exception:
Exception in thread "main" java.util.zip.ZipException: Not in GZIP format
at java.base/java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:165)
at java.base/java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:79)
at java.base/java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:91)
at GZIPStringCompression.decompress(MyClass.java:41)
at MyClass.main(MyClass.java:16)
I am not sure what I want to is even possible, that's why, want to confirm that here.
Changed this to:
class GZIPStringCompression {
public static String compress(String data) throws IOException {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(data.length());
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream);
gzipOutputStream.write(data.getBytes());
gzipOutputStream.close();
return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
}
public static String decompress(String compressed) throws IOException {
ByteArrayInputStream bis = new ByteArrayInputStream(Base64.getDecoder().decode(compressed));
GZIPInputStream gis = new GZIPInputStream(bis);
BufferedReader br = new BufferedReader(new InputStreamReader(gis, StandardCharsets.UTF_8));
StringBuilder sb = new StringBuilder();
String line;
while((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
gis.close();
bis.close();
return sb.toString();
}
}
This somehow worked. Would this be a dependable solution?
Your first solution didn't work because you wanted to take a byte array (array of 8-bit bytes) and assign it to a String attribute (basically an array of unicode characters). That doesn't make sense can can result in all sorts of unwanted manipulation for your bytes that makes them unusable when you read them back.
Your approach of converting the byte array into base-64 encoding - basically a subset of ASCII - works, because ASCII characters can indeed be represented as in the String without any manipulation and can be read back just like they were written.
Since you mentioned this is for DynamoDB, I should add the DynamoDB does have the "binary" type in addition to the "string" type, and you could just use that. In Java, you can assign the byte array directly to an attribute with of this type - and don't need to try to "convert" it into a String.
I am new to react-native and I seek your help please. What I am planning to do is to get the app icon associated with an app that the user has installed on his device.
I did take a look at this code and realized that I have no way of passing it back to my JS.
Here is what I am doing currently.
private List<String> getNonSystemApps() {
List<PackageInfo> packages = this.reactContext
.getPackageManager()
.getInstalledPackages(0);
List<String> ret = new ArrayList<>();
for (final PackageInfo p: packages) {
if ((p.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("name", p.packageName);
jsonObject.put("firstInstallTime", p.firstInstallTime);
jsonObject.put("installLocation", p.installLocation);
jsonObject.put("applicationInfo", p.applicationInfo);
jsonObject.put("permissions", getPermissionsByPackageName(p.packageName));
Drawable icon = reactContext.getPackageManager().getApplicationIcon(p.packageName);
ret.add(jsonObject.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return ret;
}
Can you please help me out with this ?
Thanks
Edit
I managed to get it working, based on Aaron's suggestion, I created another private function just to work with the images. This function will generate the base 64 version of an app's icon.
private String getBitmapOfAnAppAsBase64(String packageName) {
if(packageName.isEmpty() ) return new String("");
String base64Encoded = "";
Bitmap bitmap;
try {
Drawable appIcon = this.reactContext.getPackageManager().getApplicationIcon(packageName);
if(appIcon instanceof BitmapDrawable) {
bitmap= ((BitmapDrawable)appIcon).getBitmap();
} else {
bitmap = Bitmap.createBitmap(appIcon.getIntrinsicWidth(), appIcon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 90, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();
base64Encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);
} catch(Exception e) {
Log.d(TAG,"An error was encounted while getting the package information. The error follows : " + e.toString());
}
return base64Encoded;
}
I then use this generated string in my original function, with the following modifications.
Old Non working code
Drawable icon = reactContext.getPackageManager().getApplicationIcon(p.packageName);
New working code
jsonObject.put("icon", getBitmapOfAnAppAsBase64(p.packageName));
and then in React-Native - its a piece of pie, since it supports base64 already.
"icon" : 'data:image/png;base64,'+installAppObj.icon
Huge thanks to Aaron , for guiding me in the correct direction.
If you haven't already, read through the entire Android Native Modules page. It's not that long and addresses several issues you're likely to run into.
Only these types can be sent to your JS code (via a #ReactMethod):
Boolean -> Bool
Integer -> Number
Double -> Number
Float -> Number
String -> String
Callback -> function
ReadableMap -> Object
ReadableArray -> Array
So you effectively have two options:
Encode the Drawable to one of these types, then decode it on the JavaScript side, or
Write the file to disk, and send the path over
I'm not sure what type of Drawable the icon is or if there are guarantees. But any of them should be convertible in some way. For example if it's a Bitmap you can do a Bitmap to Base64 String conversion.
How do can I read through a baml stream that contains a ResourceDictionaory using the Baml2006Reader and without acually instantiating the the ResourceDictionary?
I can ready through regular baml that just contains a UserControl just fine and I can examine the XAML tree using Baml2006Reader.NodeType etc.
But once the reader hits a ResourceDictionary, Baml2006Reader.Member.Name is "DeferrableContent" and Baml2006Reader.Value contains a MemoryStream that can not be parsed by another instance of Baml2006Reader. I can't event instantiate the reader:
System.IO.EndOfStreamException occurred HResult=-2147024858
Message=Unable to read beyond the end of the stream. Source=mscorlib
StackTrace:
at System.IO.MemoryStream.InternalReadInt32()
at System.Windows.Baml2006.Baml2006Reader.Process_Header()
at WpfApplication10.AssemblyExtensions.Read(Stream stream, List`1 result) in d:\Documents\Visual Studio
2012\Projects\WpfApplication10\WpfApplication10\AssemblyExtensions.cs:line
84 InnerException:
It seems that whenever the Baml2006Reader encounters an element where Baml2006Reader.Member.Name is "DeferrableContent" it is followed by another node where BamlReader.Value is a MemoryStream. It seems that this stream only contains a baml fragment and does not have a header (that's why System.Windows.Baml2006.Baml2006Reader.Process_Header() fails.)
So we need to tell the baml reader to read a baml fragment. This can be done be giving the reader an instance of System.Windows.Baml2006.Baml2006ReaderSettings where the IsBamlFragment property istrue.
Unfortunately both the Baml2006ReaderSettings class and the appropriate constructor of Baml2006Reader are internal. So we need to resort to reflection:
private static string PresentationFrameworkAssemblyName = "PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
private static Baml2006Reader CreateBamlFragmentReader(MemoryStream substream, XamlSchemaContext schemaContext)
{
var bamlSettingsType =
Type.GetType(
"System.Windows.Baml2006.Baml2006ReaderSettings, " + PresentationFrameworkAssemblyName);
var settingsCtor =
bamlSettingsType.GetConstructor(Type.EmptyTypes);
var bamlSettings = settingsCtor.Invoke(null);
var isBamlFragmentProp = bamlSettingsType.GetProperty("IsBamlFragment",
BindingFlags.NonPublic |
BindingFlags.Instance);
isBamlFragmentProp.SetValue(bamlSettings, true, null);
var ctor = typeof (Baml2006Reader).GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new[]
{
typeof (Stream),
Type.GetType(
"System.Windows.Baml2006.Baml2006SchemaContext, " + PresentationFrameworkAssemblyName),
bamlSettingsType
},
null);
return (Baml2006Reader)ctor.Invoke(new[] { substream, schemaContext, bamlSettings });
}
usage:
var substream = reader.Value as MemoryStream;
if (substream != null)
{
using (var subReader = CreateBamlFragmentReader(substream, reader.SchemaContext))
{
// continue reading with subReader
}
}
I know this is rather fragile code and very hackish, but what the heck - it works (for me, currently)!
I create a file in isolated storage and then the same file is accessed and be edited on the click of button. But sometime an Exception occured with detail that operation is not allowed on isolated storage. This exception has no fixed time sometimes occured on first click of button some times it occuered after 5th or 6th click etc. ISOFileProcess(String module, String operation, String xmlObj) function in the below code is called on click of button.
public static void ISOFileProcess(String module, String operation, String xmlObj)
{
var store = IsolatedStorageFile.GetUserStoreForApplication();
if (store.FileExists(IsolatedMemFileHandlingCon.fileName) == false)
{
StreamWriter sw = new StreamWriter(store.OpenFile(IsolatedMemFileHandlingCon.fileName, FileMode.OpenOrCreate));
CreateXML(sw,module,operation,xmlObj);
sw.Close();
MessageBox.Show("File Created.");
}
else
{
//store.OpenFile(IsolatedMemFileHandlingCon.fileName, FileMode.Append);
IsolatedStorageFileStream isoStream =
new IsolatedStorageFileStream(IsolatedMemFileHandlingCon.fileName, FileMode.Append, FileAccess.ReadWrite, store);
EditXML(isoStream, module, operation, xmlObj);
isoStream.Close();
}
}
#endregion
#region XML Creation And Editing
private static void CreateXML(StreamWriter sw, String mname, String operation, String xmlObj)
{
XmlWriter xWrt = XmlWriter.Create(sw);
xWrt.WriteStartElement("ocs");
// xWrt.WriteStartElement("module");
xWrt.WriteStartElement("operation");
xWrt.WriteAttributeString("mode", operation);
xWrt.WriteAttributeString("mname", mname);
xWrt.WriteRaw(xmlObj);
xWrt.WriteEndElement();
//xWrt.WriteEndElement();
xWrt.WriteEndElement();
xWrt.Close();
}
private static void EditXML(IsolatedStorageFileStream sw, String mname, String operation, String xmlObj)
{
sw.Seek(sw.Length - 6, SeekOrigin.Begin);
XmlWriterSettings wrSettings = new XmlWriterSettings();
wrSettings.OmitXmlDeclaration = true;
XmlWriter xWrt = XmlWriter.Create(sw,wrSettings);
//xWrt.WriteStartElement("module");
xWrt.WriteStartElement("operation");
xWrt.WriteAttributeString("mode", operation);
xWrt.WriteAttributeString("mname", mname);
xWrt.WriteRaw(xmlObj);
xWrt.WriteEndElement();
//xWrt.WriteEndElement();
xWrt.WriteRaw("</ocs>");
xWrt.Close();
}
You specify FileMode.Append here:
IsolatedStorageFileStream isoStream =
new IsolatedStorageFileStream(
IsolatedMemFileHandlingCon.fileName,
FileMode.Append,
FileAccess.ReadWrite, store);
Append does not combine with FileAccess.ReadWrite and with moving the cursor before the end of the file.
In the code you use random access, moving the cursor back:
sw.Seek(sw.Length - 6, SeekOrigin.Begin);
From the MSDN:
Append Opens the file if it exists and seeks to the end of the file,
or creates a new file. FileMode.Append can only be used in conjunction
with FileAccess.Write. Attempting to seek to a position before the end
of the file will throw an IOException and any attempt to read fails
and throws an NotSupportedException.
In my MVC application, I am using following code to upload a file.
MODEL
public HttpPostedFileBase File { get; set; }
VIEW
#Html.TextBoxFor(m => m.File, new { type = "file" })
Everything working fine .. But I am trying to convert the result fiel to byte[] .How can i do this
CONTROLLER
public ActionResult ManagePhotos(ManagePhotos model)
{
if (ModelState.IsValid)
{
byte[] image = model.File; //Its not working .How can convert this to byte array
}
}
As Darin says, you can read from the input stream - but I'd avoid relying on all the data being available in a single go. If you're using .NET 4 this is simple:
MemoryStream target = new MemoryStream();
model.File.InputStream.CopyTo(target);
byte[] data = target.ToArray();
It's easy enough to write the equivalent of CopyTo in .NET 3.5 if you want. The important part is that you read from HttpPostedFileBase.InputStream.
For efficient purposes you could check whether the stream returned is already a MemoryStream:
byte[] data;
using (Stream inputStream = model.File.InputStream)
{
MemoryStream memoryStream = inputStream as MemoryStream;
if (memoryStream == null)
{
memoryStream = new MemoryStream();
inputStream.CopyTo(memoryStream);
}
data = memoryStream.ToArray();
}
You can read it from the input stream:
public ActionResult ManagePhotos(ManagePhotos model)
{
if (ModelState.IsValid)
{
byte[] image = new byte[model.File.ContentLength];
model.File.InputStream.Read(image, 0, image.Length);
// TODO: Do something with the byte array here
}
...
}
And if you intend to directly save the file to the disk you could use the model.File.SaveAs method. You might find the following blog post useful.
byte[] file = new byte[excelFile.ContentLength];
excelFile.InputStream.Read(file, 0, file.Length);
//Create memory stream object from your bytes
MemoryStream ms = new MemoryStream(file);
// Set WorkbookPart , Sheet
using (var myDoc = DocumentFormat.OpenXml.Packaging.SpreadsheetDocument.Open(ms, true))