I have a process that creates Windows internet shortcut files (.url). The files are encoded in UTF-8. The files contain an [InternetShortcut] section, where a URL= is specified. In this case, these are file:/// protocol URLs, which allow people to open paths on their LAN. The URLs are all UNC paths.
Normally the process works fine. But when a UNC path contains Unicode characters, such as the "í" from the code sample below, Windows is unable to "find" the URL when an end user tries to open the internet shortcut from Windows Explorer:
A sample file follows:
[InternetShortcut]
URL=file:///\\lt-splourde\d$\POC\Montería Test\
IconIndex=1
When I open the sample .url file above with a text editor, I see the path with the proper Unicode characters. But when I try to open the file from Windows Explorer, in order to access the path, Windows reports that it is unable to access the path, and it seems to mangle the Unicode characters.
The source code that creates these shortcuts follows:
private void CreateShortcutAsUrl(string uncRootPath, string name, string path, int projectId)
{
path = path + (path.EndsWith(#"\") ? "" : #"\");
using (StreamWriter writer = new StreamWriter(
String.Format(#"{0}\{1}\{2}.url", uncRootPath,
ShortcutsDirectory, new FileServerController().SanitizeNameForDirectory(name)),
false, Encoding.UTF8))
{
writer.WriteLine(#"[InternetShortcut]");
writer.WriteLine(#"URL=file:///" + path);
writer.Flush();
}
}
Does anyone know of a solution for this issue?
Thanks!
(I had posted this on superuser originally, but I feel like the content is more programmer oriented)
Try the .NET equivalent of InternetCanonicalizeUrl, which is System.Uri.EscapeUriString, so something like this (assuming your URI is in szOriginalString
String szEscapedString = System.Uri.EscapeUriString(szOriginalString);
Then write szEscapedString as the URI instead of the original.
Related
I have a Xamarin application running on Windows, and I have a method which includes an opening of a pdf file like this:
var psi = new ProcessStartInfo
{
FileName = "cmd",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false,
CreateNoWindow = true,
Arguments = $"/c start {filename}"
};
Process.Start(psi);
When this executes, the windows opens a dialog with the following message:
Windows cannot access the specified device, path, or file. You may not have the appropriate permissions to access the item.
The filename is a pdf file located in the LocalApplicationData, and I also have a database there, and the application is normally creating a database there and manipulates with it, so it should have a permission to access that folder. Also, when I run that pdf with double-click outside the application, the pdf opens normally with Chrome. How to solve this?
Unless you have a file there called "cmd" this won't work, as you have declared your filename as a string with the value "cmd".
I have tried unsuccessfully to open image file that it's name contains a space.
I use the following call:
WWW www = new WWW(url);
where:
url = "C:\Users\user\Documents\Files\Thumbnails\sample image.png";
A red question mark appears instead of image.
Also a 404 error appears when print www.error.
If I use another .png file without space (sampleimage.png), it works perfectly. On Windows and Editor it works nice too.
So I tried to replace the space with %20 but an error "can't load the file" appears.
I have also tried WWW.EscapeURL applied on the filename ... but nothing works.
Try to use verbatim string along with file:// prefix:
string filePrefix = #"file://";
string url = #"C:\Users\user\Documents\Files\Thumbnails\sample image.png";
Is there a way to copy (or cut) a file to the Windows clipboard from the command line?
In particular with a batch script. I know how to copy the contents to the clipboard (type file | clip), but this is not the case. I want to have the whole file as I would press Ctrl + C in Windows Explorer.
OK, it seems the easiest way was to create a small C# tool that takes arguments and stores them in the clipboard:
using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections.Specialized;
namespace File2Clip
{
public class App
{
[STAThread]
static void Main(string[] args)
{
List<string> list = new List<string>();
string line;
while(!string.IsNullOrEmpty(line = Console.ReadLine())) list.Add(line);
foreach (string s in args) list.Add(s);
StringCollection paths = new StringCollection();
foreach (string s in list) {
Console.Write(s);
paths.Add(
System.IO.Path.IsPathRooted(s) ?
s :
System.IO.Directory.GetCurrentDirectory() +
#"\" + s);
}
Clipboard.SetFileDropList(paths);
}
}
}
2017 edit: Here's a github repo with both source and binary.
This would place the contents of the file into the clipboard (accomplished by clip.exe).
type \path\to\file|clip
To get the actual file, you'll probably have to resort to some other programming language, like VBScript or PowerShell to access Windows API's. I'm not entirely certain what Explorer puts into the clipboard when you CTRL+C a file. I suspect it uses the notification system to do something more intelligent than put the path to the file there. Depending on the context of the CTRL+V, you'll get something (Explorer, Word) or nothing (Notepad).
I've forever wanted this to use in Emacs, so, inspired by this question, an answer here, and a goodly amount of NIH syndrome, I've written a C version available at
https://github.com/roryyorke/picellif
picellif also handles wildcards (it's not clear to me if rostok's C# version does or not).
copy and move are (some of) the batch commands that copy/paste and cut/paste files, respectively. We don't use the terms paste or cut when dealing with files but if I understand you there is a need to copy a file to another location and to move files to another location.
You can try Swiss File Knife (SFK):
sfk toclip
Copy stdin to clipboard as plain text.
type test.txt | sfk toclip
Copies the content of ASCII file test.txt into the clipboard.
sfk list | sfk toclip
Copies a file listing of the current dir into the clipboard.
sfk fromclip [-wait] [-clear]
Dump plain text content from the clipboard to the terminal.
-wait : block until plain text is available.
-clear: empty the clipboard after reading it.
Example: turn backslashes into forward slashes. Imagine you have the following text open within Notepad:
foo/bar/systems/alpha1.cpp
foo/bar/systems/alpha2.cpp
foo/bar/systems/beta1.cpp
And for some reason you need the first line in a format like this:
foo\bar\systems\alpha1.cpp
Then you may do it this way:
Mark the first line using SHIFT + CURSOR keys.
Press Ctrl + C or Ctrl + Insert to copy it into clipboard
On the Windows command line, run this command (for example, from a batch file):
sfk fromclip +filter -rep x/x\x +toclip
Back in the editor, press Ctrl + V or Shift + Insert, pasting the result from the clipboard.
As you see, the line changed into "foo\bar\systems\alpha1.cpp".
You can use Command Line Copy and Paste Files utilities on Sid's Bytestream.
I am trying get the parent folder of a Windows user's profile path. But I couldn't find any "parameter" to get this using SHGetSpecialFolderPath, so far I am using CSIDL_PROFILE.
Expected Path:
Win7 - "C:\Users"
Windows XP - "C:\Documents and Settings"
For most purposes other than displaying the path to a user, it should work to append "\\.." (or "..\\" if it ends with a backslash) to the path in question.
With the shell libary version 6.0 you have the CSIDL_PROFILES (not to be confused with CSIDL_PROFILE) which gives you what you want. This value was removed (see here), you have to use your own workaround.
On any prior version you'll have to implement your own workaround, such as looking for the possible path separator(s), i.e. \ and / on Windows, and terminate the string at the last one. A simple version of this could use strrchr (or wcsrchr) to locate the backslash and then, assuming the string is writable, terminate the string at that location.
Example:
char* path;
// Retrieve the path at this point, e.g. "C:\\Users\\username"
char* lastSlash = strrchr(path, '\\');
if(!lastSlash)
lastSlash = strrchr(path, '/');
if(lastSlash)
*lastSlash = 0;
Or of course GetProfilesDirectory (that eluded me) which you pointed out in a comment to this answer.
How do I register a custom protocol with Windows so that when clicking a link in an email or on a web page my application is opened and the parameters from the URL are passed to it?
Go to Start then in Find type regedit -> it should open Registry editor
Click Right Mouse on HKEY_CLASSES_ROOT then New -> Key
In the Key give the lowercase name by which you want urls to be called (in my case it will be testus://sdfsdfsdf) then Click Right Mouse on testus -> then New -> String Value and add URL Protocol without value.
Then add more entries like you did with protocol ( Right Mouse New -> Key ) and create hierarchy like testus -> shell -> open -> command and inside command change (Default) to the path where .exe you want to launch is, if you want to pass parameters to your exe then wrap path to exe in "" and add "%1" to look like: "c:\testing\test.exe" "%1"
To test if it works go to Internet Explorer (not Chrome or Firefox) and enter testus:have_you_seen_this_man this should fire your .exe (give you some prompts that you want to do this - say Yes) and pass into args testus://have_you_seen_this_man.
Here's sample console app to test:
using System;
namespace Testing
{
class Program
{
static void Main(string[] args)
{
if (args!= null && args.Length > 0)
Console.WriteLine(args[0]);
Console.ReadKey();
}
}
}
Hope this saves you some time.
The MSDN link is nice, but the security information there isn't complete. The handler registration should contain "%1", not %1. This is a security measure, because some URL sources incorrectly decode %20 before invoking your custom protocol handler.
PS. You'll get the entire URL, not just the URL parameters. But the URL might be subject to some mistreatment, besides the already mentioned %20->space conversion. It helps to be conservative in your URL syntax design. Don't throw in random // or you'll get into the mess that file:// is.
If anyone wants a .reg file for creating the association, see below:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\duck]
"URL Protocol"=""
[HKEY_CLASSES_ROOT\duck\shell]
[HKEY_CLASSES_ROOT\duck\shell\open]
[HKEY_CLASSES_ROOT\duck\shell\open\command]
#="\"C:\\Users\\duck\\source\\repos\\ConsoleApp1\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.exe\" \"%1\""
Pasted that into notepad, the file -> save as -> duck.reg, and then run it. After running it, when you type duck://arg-here into chrome, ConsoleApp1.exe will run with "arg-here" as an argument. Double slashes are required for the path to the exe and double quotes must be escaped.
Tested and working on Windows 11 with Edge (the chrome version) and Chrome
There is an npm module for this purpose.
link :https://www.npmjs.com/package/protocol-registry
So to do this in nodejs you just need to run the code below:
First Install it
npm i protocol-registry
Then use the code below to register you entry file.
const path = require('path');
const ProtocolRegistry = require('protocol-registry');
console.log('Registering...');
// Registers the Protocol
ProtocolRegistry.register({
protocol: 'testproto', // sets protocol for your command , testproto://**
command: `node ${path.join(__dirname, './index.js')} $_URL_`, // $_URL_ will the replaces by the url used to initiate it
override: true, // Use this with caution as it will destroy all previous Registrations on this protocol
terminal: true, // Use this to run your command inside a terminal
script: false
}).then(async () => {
console.log('Successfully registered');
});
Then suppose someone opens testproto://test
then a new terminal will be launched executing :
node yourapp/index.js testproto://test
It also supports all other operating system.