Several frameworks and languages seem to have lnk file parsers (C#, Java, Python, certainly countless others), to get to their targets, properties, etc. I'd like to know what is the general approach to reading lnk files, if I want to parse the lnk in another language that does not have said feature. Is there a Windows API for this?
There is not an official document from Microsoft describing lnk file format but there are some documents which have description of the format. Here is one of them: Shortcut File Format (.lnk)
As for the API you can use IShellLink Interface
Simply use lnk file parser at J.A.F.A.T. Archive of Forensics Analysis Tools project.
See lnk-parse-1.0.pl at http://jafat.sourceforge.net
There seems no have no dependencies. Syntax is simple and link file becomes a simple text in standard output and to be usable on Linux.
This is an old post, but here is my C# implementation for lnk processing that handles the entire spec, more info and command line tool on this blogspot page.
Using WSH-related components seems the most convenient option to read .lnk files in most languages on a post-XP windows system. You just need access to the COM environment and instantiate the WScript.Shell Component. (remember that on win, references to the Shell usually refer to explorer.exe)
The following snippet, e.g. does the thing on PHP: (PHP 5, using the COM object)
<?php
$wsh=new COM('WScript.Shell'); // the wsh object
// please note $wsh->CreateShortcut method actually
// DOES THE READING, if the file already exists.
$lnk=$wsh->CreateShortcut('./Shortcut.lnk');
echo $lnk->TargetPath,"\n";
This other one, instead, does the same on VBScript:
set sh = WScript.CreateObject("WScript.Shell")
set lnk = sh.CreateShortcut("./Shortcut.lnk")
MsgBox lnk.TargetPath
Most examples in the field are written in VB/VBS, but they translate well on the whole range of languages supporting COM and WSH interaction in a form or another.
This simple tutorial may come handy, as it lists and exemplifies some of the most interesting properties of a .lnk file other than the most important: TargetPath. Those are:
WindowStyle,
Hotkey,
IconLocation,
Description,
WorkingDirectory
here's some C# code using the Shell32 API, from my "ClearRecentLinks" project at https://github.com/jmaton/ClearRecentLinks
To use this your C# project has to reference c:\windows\system32\shell32.dll
string linksPath = "c:\some\folder";
Type shell32Type = Type.GetTypeFromProgID("Shell.Application");
Object shell = Activator.CreateInstance(shell32Type);
Shell32.Folder s32Folder = (Shell32.Folder)shell32Type.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { linksPath });
foreach (Shell32.FolderItem2 item in s32Folder.Items())
{
if (item.IsLink)
{
var link = (Shell32.ShellLinkObject)item.GetLink;
if (link != null && !String.IsNullOrEmpty(link.Target.Path))
{
string linkTarget = link.Target.Path.ToLower();
// do something...
}
}
}
#Giorgi: Actually, there is an official specification of lnk files, at least it is claimed so.
However, for some reason, the link seems to be dead, and after downloading the whole (45 MB) doc package (Application_Services_and_NET_Framework.zip), it appears that it does not include the file MS-SHLLINK.pdf.
But is this really surprising ?
Once you got the file format, shouldn't be too hard to write code to read it.
Related
In ASP.NET Core, the JsonConfigurationProvider will load configuration from appsettings.json, and then will read in the environment version, appsettings.{Environment}.json, based on what IHostingEnvironment.EnvironmentName is. The environment version can override the values of the base appsettings.json.
Is there any reasonable way to preview what the resulting overridden configuration looks like?
Obviously, you could write unit tests that explicitly test that elements are overridden to your expectations, but that would be a very laborious workaround with upkeep for every time you change a setting. It's not a good solution if you just wanted to validate that you didn't misplace a bracket or misspell an element name.
Back in ASP.NET's web.config transforms, you could simply right-click on a transform in Visual Studio and choose "Preview Transform". There are also many other ways to preview an XSLT transform outside of Visual Studio. Even for web.config parameterization with Parameters.xml, you could at least execute Web Deploy and review the resulting web.config to make sure it came out right.
There does not seem to be any built-in way to preview appsettings.{Environment}.json's effects on the base file in Visual Studio. I haven't been able to find anything outside of VS to help with this either. JSON overriding doesn't appear to be all that commonplace, even though it is now an integral part of ASP.NET Core.
I've figured out you can achieve a preview with Json.NET's Merge function after loading the appsettings files into JObjects.
Here's a simple console app demonstrating this. Provide it the path to where your appsettings files are and it will emit previews of how they'll look in each environment.
static void Main(string[] args)
{
string targetPath = #"C:\path\to\my\app";
// Parse appsettings.json
var baseConfig = ParseAppSettings($#"{targetPath}\appsettings.json");
// Find all appsettings.{env}.json's
var regex = new Regex(#"appsettings\..+\.json");
var environmentConfigs = Directory.GetFiles(targetPath, "*.json")
.Where(path => regex.IsMatch(path));
foreach (var env in environmentConfigs)
{
// Parse appsettings.{env}.json
var transform = ParseAppSettings(env);
// Clone baseConfig since Merge is a void operation
var result = (JObject)baseConfig.DeepClone();
// Merge the two, making sure to overwrite arrays
result.Merge(transform, new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Replace
});
// Write the preview to file
string dest = $#"{targetPath}\preview-{Path.GetFileName(env)}";
File.WriteAllText(dest, result.ToString());
}
}
private static JObject ParseAppSettings(string path)
=> JObject.Load(new JsonTextReader(new StreamReader(path)));
While this is no guarantee there won't be some other config source won't override these once deployed, this will at least let you validate that the interactions between these two files will be handled correctly.
There's not really a way to do that, but I think a bit about how this actually works would help you understand why.
With config transforms, there was literal file modification, so it's easy enough to "preview" that, showing the resulting file. The config system in ASP.NET Core is completely different.
It's basically just a dictionary. During startup, each registered configuration provider is run in the order it was registered. The provider reads its configuration source, whether that be a JSON file, system environment variables, command line arguments, etc. and builds key-value pairs, which are then added to the main configuration "dictionary". An "override", such as appsettings.{environment}.json, is really just another JSON provider registered after the appsettings.json provider, which obviously uses a different source (JSON file). Since it's registered after, when an existing key is encountered, its value is overwritten, as is typical for anything being added to a dictionary.
In other words, the "preview" would be completed configuration object (dictionary), which is composed of a number of different sources, not just these JSON files, and things like environment variables or command line arguments will override even the environment-specific JSON (since they're registered after that), so you still wouldn't technically know the the environment-specific JSON applied or not, because the value could be coming from another source that overrode that.
You can use the GetDebugView extension method on the IConfigurationRoot with something like
app.UseEndpoints(endpoints =>
{
if(env.IsDevelopment())
{
endpoints.MapGet("/config", ctx =>
{
var config = (Configuration as IConfigurationRoot).GetDebugView();
return ctx.Response.WriteAsync(config);
});
}
});
However, doing this can impose security risks, as it'll expose all your configuration like connection strings so you should enable this only in development.
You can refer to this article by Andrew Lock to understand how it works: https://andrewlock.net/debugging-configuration-values-in-aspnetcore/
I've seen that some projects used _ function that takes string as an argument, like _("Hello World"). But I couldn't find any manuals or articles about what is it and how to use it.
I guess this has something to do with i18n and l10n (it was mentioned in some article I found on the internet), but can you explain to me how it works and how to use it?
That is the GNU gettext localization function. You can provide language specific alternate strings for the one specified in the function call.
There is the xgettext tool, which generates a .pot file (abbreviation for portable object template) from your application code, then translators can make .po localization files for it. Then, you can bundle these with your application, and deliver a more widely usable piece of software.
I18n. See gettext example here: https://ewgeny.wordpress.com/2012/05/10/supporting-multiple-languages-in-your-application-a-simple-gettext-step-by-step-example/
Also found some info about what exactly this function do, it seems to be the macro for Glib.dgettext() function in Vala, this is from valadoc.org:
dgettext
public unowned string dgettext (string? domain, string msgid)
This function is a wrapper of dgettext which does not translate the message if the default domain as set with textdomain has no translations for the current locale.
...
Applications should normally not use this function directly, but use the _ macro for translations.
I have recently picked up flixel (I have programmed before, but I have not in a while) and I have come across a problem. I am attempting to create maps, and eventually there will be multiple maps available.
I currently have a .txt file that has information that eventually goes into an array. Then I go from array to map with loadmap. It is maybe a simple way to accomplish this task, and maybe their are better ways (I have not explored all the possibilities with flixel, and if there are any opinions, go ahead and let me know) but it works good for now.
As I have previously said, I am trying to do this with multiple maps. I could do this by using [Embed(source = "")] for each .txt file, but this may end up being annoying. So, here is my question: Is there a possible way Embed a file based upon a variable?
My Map class looks like this:
public function Map(MapSet:String, TileSet:String)
{
super(MapSet, TileSet);
//more stuff
}
Now I have tried:
[Embed(scource="data/MapSets/" + MapSet + ".txt", mimeType = "application/octet-stream")]private var loadedMap:Class
and then I use:
map = new Map("Map1x1", "ForestTiles");
add(map);
Is there a possibility of doing this in a different way? Or maybe I am doing something wrong? All opinions are welcome.
It's beneficial to know what code does when using it.
Embed is a meta tag. It tells the compiler to include a certain file into the .swf file.
That means this does not happen at runtime.
When this embed code is "executed", your variables don't even exist yet.
That's why your code cannot work.
Despite not working, your solution is still valid:
If you find it tedious to generate code, write a program that does this for you. Create/use a program that finds all valid files in the given directory and creates all the embed tags. Run this program before the compiler.
To embed a text file and use as a string, try this:
// create source var TextSource
[Embed(source="textFile.txt",mimeType="application/octet-stream")]
private var TextSource:Class;
var myByteArray:ByteArray = new TextSource();
var myString:String = myByteArray.readUTFBytes(myByteArray.length);
// then use for your function
map = new Map("Map1x1", myString);
My app runs in WPF and Android (Windows Phone later) with mvvmcross as framework. I implemented localization with JsonLocalisation like the Babel (N21) example and it is working fine in Android. But whatever I try in WPF I get this message;
mvx:Warning: 0,22 Language file could not be loaded for Danish.SettingsViewModel -
FileNotFoundException: Unable to find resource file MyAppResources/Text/Danish/SettingsViewModel.json
at Cirrious.MvvmCross.Plugins.JsonLocalisation.MvxContentJsonDictionaryTextProvider.
LoadJsonFromResource(String namespaceKey, String typeKey, String resourcePath) at >Cirrious.MvvmCross.Plugins.JsonLocalisation.MvxTextProviderBuilder.LoadResources(String >whichLocalisationFolder)"
Stuart says in his video tutorial that the json translation files must be included as "Content" and not copied to the output folder - like;
But looking at the compiled executable with "dotPeek" doesn't reveal the files.
Am I missing something obvious? Any hints would be highly appreciated. Even confirmation from somebody who has JsonLocalisation working in WPF would be nice.
EDIT:
Well, I tried this code in my WPF mainWindow. I understand this call is used internally in MvxWPFResourceLoader.
public MainWindow()
{
....
//This return null without exceptions.
var t = Application.GetResourceStream(new Uri("MyAppResources/Text/Danish/SettingsViewModel.json", UriKind.Relative));
//This throwns an IOException; Cannot locate resource 'thisdoesnotexist/text/danish/settingsviewmodel.json'.
var y = Application.GetResourceStream(new Uri("ThisDoesNotExist/Text/Danish/SettingsViewModel.json", UriKind.Relative));
}
It seems when the path if wrong an exception is thrown. When it is correct it just returns null!!?! I am a bit puzzled, any ideas?
Best regards
Thank you for such fast answer (and for mvvmcross!).
The link you provided is to a Babel solution with a WPF sample - exactly what I needed. I mistakenly used the one from N21 without WPF sample :-)
Anyway, when looking at the sample I noticed that the json files must be included as 'Resource' and not 'Content'. That made all the difference - hurray!
Best regards
1. Compiled Assembly from JSC
I've compiled what is intended to be client-side JavaScript using the JScript compiler (jsc.exe) on the server side in an attempt to make something that can be tested from a unit testing project, and maybe even something that can be debugged on the server side.
The compiled file contains only functions as follows (just for example) and it compiles fine into BitField.exe. Notice, no wrapper class or package in the source code.
------ BEGIN FILE (BitField.js) -------
function BitField(){
this.values = [];
}
// more functions ...
------- END FILE -------
jsc /fast- /out:BitField.exe Bitfield.js
Results in a BitField.exe assembly.
Success! Well, kind of ....
2. Testing Assembly / Access Point?
Secondly I've created a test project (in C#) and referenced in the BitField.exe assembly successfully. (The type of project is irrelevant but I'm providing more description to paint a full picture.)
The problem seems to be: I cannot find the namespace or a point at which I can access the BitField functions inside the BitField.exe assembly from my C# test project. The assembly doesn't seem to be a "normal".
In other words I need in C#
using ???WHAT???
Note: I don't want to use JScript "extensions", meaning keywords that won't run client-side (in a web browser), for example, class, package etc because I want the code to be clean as possible for copy & paste back into client side script environment (Regardless said "clean" code compiles fine by jsc.exe without use of those extensions). When I try to wrap the functions in package and class it starts producing compile errors so that's another reason not to use them - because they appear to make me alter my code.
Any suggestions as to how I can use the functions of the compiled JScript assembly (by having it referenced into another assembly) when there are no explicit containers in it?
Update / Proof
.NET Reflector view
After playing around with it for a while, and trying various combinations of command-line switches for jsc.exe, I'm pretty sure that what you're trying to do won't work as you'd wish it to. If you try to compile a js file that contains functions into a .Net library assembly, you get an error:
BitField.js(1,1) : error JS1234: Only type and package definitions are allowed inside a library
But, there is hope, yet! Here's what I would do...
I would keep your "clean" BitField.js file just as it is, and then create a batch file that wraps it in a JScript class and writes it out to a "dirty" js file. It's pretty clean if you think of it as part of the compilation of the code into the DLL. The code to wrap the BitField.js into BitFieldClass.js would look like this:
merge-into-class.js
var fso = new ActiveXObject("Scripting.FileSystemObject");
var ForReading = 1;
var inputFile = fso.OpenTextFile("BitField.js",ForReading, false);
var outputFile = fso.CreateTextFile("BitFieldClass.js", true);
outputFile.write("class BitFieldClass{\n");
while (!inputFile.AtEndOfStream)
{
var textLine = inputFile.ReadLine();
outputFile.write (textLine + "\n");
}
outputFile.write("}");
outputFile.close();
Then the batch file to wrap it and compile it is really simple:
compile-js.bat
cscript merge-into-class.js
jsc /t:library /out:BitFieldClass.dll bitFieldClass.js
Of course, if you wanted to do multiple files, you'd have to parameterize things a bit, but hopefully this is enough to demonstrate the idea.