I am working on a Wix installer that creates a SymbolicLink inside a custom action. The custom action is written in C#. It is creating the SymbolicLink by calling the CreateSymbolicLink Win32 API. On Windows 10, the call works perfectly. On Windows 7 it fails. If I call Marshal.GetLastWin32Error(), it returns an error code of 997, which is ERROR_IO_PENDING
Here is the line of code the calls the API:
var result = CreateSymbolicLink(pathToCreateLink, installDir, SymbolicLinkFlags.Directory | SymbolicLinkFlags.UnprivilegedCreate);
if(!result)
{
_logger.Log($"Win32 Error Code: {Marshal.GetLastWin32Error()}");
}
Here is the Dll Import:
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool CreateSymbolicLink( string lpSymlinkFileName, string pTargetFileName, SymbolicLinkFlags dwFlags);
The custom action is invoked with Execute set to "deferred" and Impersonate set to "no".
If I put the line of C# code in a console application, it functions correctly (even on Windows 7). So there is something about how the code is being called in the installer that is causing the error.
Part of my problem is that I can find very little information on the error code, so I can't be sure what to try to fix it.
A kind of confirmation can be found in wixsharp code. They encountered this problem and could not surpass it.
https://github.com/oleg-shilo/wixsharp/blob/master/Source/src/WixSharp/ResilientPackage.cs
The w/a I implemented in my installer is repeating symbolic links creation via cmd tool mklink and if it fails as well, just copy files.
MSI packages run as System TrustedInstaller, and on Windows 7 that user does not have access to create SymLinks with the default Local Security Policy.
I fixed it by using junctions instead (mklink /j), but that only works for folders.
Related
no Error just nothing happen and file target still there in my path
public void keyboard(){
ProcessStartInfo touchkey = new ProcessStartInfo(#"C:\Program
Files\Common Files\microsoft shared\ink\TabTip.exe");
touchkey.WorkingDirectory = #"C:\";
touchkey.WindowStyle = ProcessWindowStyle.Hidden;
Process.Start(touchkey);
}
Update
The suggested solution threw a `UnauthorizedAccessException`:
var path = #"ms-appx://C:/Program Files/Common Files/microsoft
shared/ink/TabTip.exe";
var file = await
Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(path);
await Windows.System.Launcher.LaunchFileAsync(file);
Update2
I try to use FullTrustProcessLauncher it's work fine but like code before Keyboard tabtip.exe not show I dont know what should I do
await Dispatcher.RunAsync(CoreDispatcherPriority.High, () =>
{
FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
});
UWP applications are sandboxed and cannot launch other processes directly due to security restrictions.
The only way to launch other applications is if those applications have a URI registered, or an application is a default handler for a particular file type.
In those instances, you can use methods such as LaunchUriAsync or LaunchFileAsync
Without TabTip.exe
I recognize you are trying to show the on-screen keyboard judging by the path of the exe. I suggest a better approach would be to trigger the new touch-enabled keyboard which is easily possible without additional hassle from UWP with InputPane API:
var pane = InputPane.GetForCurrentView();
pane.TryShow();
With TabTip.exe
If you prefer the older on-screen keyboard for some reason, you have two problems with your existing code.
Firstly, ms-appx: scheme is used to refer to files at the application installation path. The path you require is an absolute path, so you can't use it there.
Secondly, as this is an arbitrary path on the hard drive, you don't have access to it directly (as UWP apps run in a sandbox and can't access the filesystem directly for security reasons). To access the file, you will need to declare the broadFileSystemAccess capability, which will then allow you to initialize the StorageFile instance. You can check for example this SO question to learn how to do just that.
Note: I don't have my VS PC around so I can't say for sure if this will allow you to launch the executable or not, as that seems like an additional permission which may not be granted. In case this fails, I strongly recommend the first solution.
Make sure you edited the manifest file and add the extension for full trust process in the application.
We have an application designed for google chrome where we need to add a link to the network file share. Unfortunately, Chrome denies the file:// protocol for security purposes. We want to set up a custom protocol to allow this functionality.
I thought a good way to do this would be to call explorer. Here are the registry keys we added:
[HKEY_CLASSES_ROOT\MyApp\DefaultIcon]
#="\"C:\\Windows\\explorer.exe\""
[HKEY_CLASSES_ROOT\MyApp\shell]
[HKEY_CLASSES_ROOT\MyApp\shell\open]
[HKEY_CLASSES_ROOT\MyApp\shell\open\command]
#="\" C:\\Windows\\explorer.exe\" \"%1\""
Currently, we get an error that states the protocol isn't valid. Could anyone assist in correcting this?
Thank you all very much in advance.
# Wolfram Schmied,
I just wrote a workaround on yours, using CMD:
REGEDIT4
[HKEY_CLASSES_ROOT\IntranetFileLauncher]
#="URL:IntranetFileLauncher Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\IntranetFileLauncher\DefaultIcon]
#="\"C:\\Windows\\explorer.exe\""
[HKEY_CLASSES_ROOT\IntranetFileLauncher\shell]
[HKEY_CLASSES_ROOT\IntranetFileLauncher\shell\open]
[HKEY_CLASSES_ROOT\IntranetFileLauncher\shell\open\command]
#="cmd /c set url=\"%1\" & call set url=%%url:intranetfilelauncher:=%% & call start explorer file:%%url%%"
The code above basically does the same as yours, except on the last line it uses cmd.exe to open a file/folder a command.
In pseudo code: open commandpromt, pass given filepath as variable 'url', alter variable 'url' by stripping the protocol identifier and finally open explorer with the stripped filepath
I hope this helpes.
I got the following to work on Windows 8 / Firefox.
The correct way to register a custom protocol is described in this MSDN article.
Sadly, you cannot apply this directly to the Windows Explorer. If you do, you'll find that the Explorer starts spawning copies until either your memory or your patience runs out, and you'll have to log off to stop it. The reason is that the application handling the protocol is passed the entire link including the protocol specification. I. e., if you have a link
localdir:D:\somefolder,
the resulting call will not be
explorer D:\somefolder,
but
explorer localdir:D:\somefolder.
This is apparently done so that the same application can handle several protocols. But Explorer doesn't recognize that it is meant to handle the request, and instead starts the resolution process anew, which sets the vicious circle in motion.
To deal with this, you call a simple helper app that removes the protocol specification from the argument, and then calls Explorer with the cleaned string.
As an example, I created a bare bones Java class Stripper.
import java.io.IOException;
public class Stripper {
public static void main(String[] args) {
String stripped = args[0].substring("localdir:".length());
try {
Runtime.getRuntime().exec("C:\\Windows\\explorer.exe "+stripped);
}
catch (IOException e) { /* error handling */ }
}
}
The following is a .reg file adding the required keys to the registry. This assumes that Stripper is located in the folde D:\Stripper.
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\localdir]
#="URL: localdir Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\localdir\shell]
[HKEY_CLASSES_ROOT\localdir\shell\open]
[HKEY_CLASSES_ROOT\localdir\shell\open\command]
#="cmd /c \"cd /d d:\\Stripper & java Stripper %1\""
The command invokes the command line interpreter, telling it to first change to the directory containing our helper, and then to call the JRE to execute it. It's a bit awkward, but it works.
With a native .exe file, the command key could look like this:
[HKEY_CLASSES_ROOT\localdir\shell\open\command]
#="<somepath>Stripper.exe %1"
This is a quick'n'dirty solution, you'll want to obviously want to add checks and balances and probably more mechanics, but the general approach looks workable.
Same task here, same solution first as #mdbxz and after with VBScript to not showing cmd black box:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\explorer]
#="URL:VIR Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\explorer\shell]
[HKEY_CLASSES_ROOT\explorer\shell\open]
[HKEY_CLASSES_ROOT\explorer\shell\open\command]
#="mshta vbscript:Close(Execute(\"CreateObject(\"\"WScript.Shell\"\").Run Join(Array(\"\"iexplore.exe\"\",Replace(\"\"%1\"\",\"\"explorer\"\",\"\"https\"\"))), 1, True\"))"
The problem with these that if we click on same link in Explorer it handles the same, so it opens a new window, not just jump to the link. Also the question that if we want open the given app with the protocol.
Can we register the new protocol to Explorer, so it translate to https? Then we wont needed to replace protocol.
This problem I am having is very easy to reproduce. Create a basic MFC MDI application with file extension as .xyz using Visual Studio 2010. The application default code readily registers the file associations via calls:
// Enable DDE Execute open
EnableShellOpen();
RegisterShellFileTypes(TRUE);
The problem is that inside RegisterShellFileTypes(TRUE), the call below fails:
if (!_AfxSetRegKey(strFileTypeId, strFileTypeName))
continue; // just skip it
The file is obviously not being registered and it doesn't adopt the application assigned file icon. All I want is when I double click the registered file type (in this case .xyz) it should open in the application but it doesn't. What is possibly missing..how to make this work?
Microsoft has changed their concept of registering an extension over the years. Starting with Vista, it's expected that the extension will be registered at installation time with a Setup application which will have Admin privileges. The registry keys necessary to map an extension to an application are now in a protected area of the registry. What you're asking for is no longer possible.
You need administrator privileges to accomplish this. Usually, you should let your installer register your files. However, it can be done if you explicitly elevate (and re-run) your process before your file types are registered:
// In your InitInstance, do the following:
OSVERSIONINFOEX osvi;
osvi.dwOSVersionInfoSize = sizeof OSVERSIONINFOEX;
GetVersionEx((OSVERSIONINFO*)&osvi);
if (osvi.dwMajorVersion >= 6) // XP or Vista/elevated?
{
TCHAR exePath[MAX_PATH];
GetModuleFileName(NULL, exePath, MAX_PATH);
ShellExecute(NULL, _T("runas"), exePath, NULL, NULL, SW_SHOWNORMAL);
return FALSE;
}
As Parapura Rajkumar mentioned, if you put this code in your init instance:
// Enable DDE Execute open
EnableShellOpen();
RegisterShellFileTypes(TRUE);
The application should run at least one time as admin (right click and run as administrator) to register file types in windows registry.
I use SHBrowseForFolder in my code. It works well in XP. But I find it dose not run well in Windows 7 with the same code. When I click a network, it does nothing. But it can expand in XP. By the way, I have the permission to access the network of another computer and I try accessing the resource with explorer, it's OK!
Can anyone tell me how to fix this problem?
Not sure it is the help you wanted, but I found this on the function's MSDN page:
For Windows Vista or later, it is
recommended that you use IFileDialog
with the FOS_PICKFOLDERS option rather
than the SHBrowseForFolder function.
This uses the Open Files dialog in
pick folders mode and is the preferred
implementation.
It should be:
BROWSEINFO bi;
// ..... omit oters
bi.ulFlags = /*BIF_DONTGOBELOWDOMAIN |*/ BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
I add one more flag BIF_BROWSEFORCOMPUTER to the ulFlags
There is a mixup here of the FileDialog APIs of COMMDLG and the IFileDlg interface, the latter existing in Vista and Win2008 Server only.
When an application crashes on Windows and a debugger such as Visual Studio is installed the following modal dialog appears:
[Title: Microsoft Windows]
X has stopped working
A problem caused the program to stop
working correctly. Windows will close
the program and notify you if a
solution is available.
[Debug][Close Application]
Is there a way to disable this dialog? That is, have the program just crash and burn silently?
My scenario is that I would like to run several automated tests, some of which will crash due to bugs in the application under test. I don't want these dialogs stalling the automation run.
Searching around I think I've located the solution for disabling this on Windows XP, which is nuking this reg key:
HKLM\Software\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger
However, that did not work on Windows Vista.
To force Windows Error Reporting (WER) to take a crash dump and close the app, instead of prompting you to debug the program, you can set these registry entries:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting]
"ForceQueue"=dword:00000001
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Consent]
"DefaultConsent"=dword:00000001
After this is set, when your apps crash, you should see *.hdmp and *.mdmp files in:
%ALLUSERSPROFILE%\Microsoft\Windows\WER\
See here:
http://msdn.microsoft.com/en-us/library/bb513638.aspx
regedit
DWORD HKLM or HKCU\Software\Microsoft\Windows\Windows Error Reporting\DontShowUI = "1"
will make WER silently report. Then you can set
DWORD HKLM or HKCU\Software\Microsoft\Windows\Windows Error Reporting\Disabled = "1"
to stop it from talking to MS.
I'm not sure if this refers to exactly the same dialog but here is an alternative approach from Raymond Chen:
DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
I had to disable this for release automation work on Windows 64-bits for Firefox and I did the following:
gpedit.msc
Computer configuration -> Administrative Templates
Windows Components -> Windows Error Reporting
Set "Prevent display of the user interface for critical errors" to Enabled
It is similar what was accomplished for Customer Experience reporting in:
http://www.blogsdna.com/2137/fix-windows-installer-explorer-update-has-stopped-working-in-windows-7.htm
In my context, I only want to suppress the popup for my unit tests and not for the entire system. I've found that a combination of functions are needed in order to suppress these errors, such as catching unhandled exceptions, suppressing run time checks (such as the validity of the stack pointer) and the error mode flags. This is what I've used with some success:
#include <windows.h>
#include <rtcapi.h>
int exception_handler(LPEXCEPTION_POINTERS p)
{
printf("Exception detected during the unit tests!\n");
exit(1);
}
int runtime_check_handler(int errorType, const char *filename, int linenumber, const char *moduleName, const char *format, ...)
{
printf("Error type %d at %s line %d in %s", errorType, filename, linenumber, moduleName);
exit(1);
}
int main()
{
DWORD dwMode = SetErrorMode(SEM_NOGPFAULTERRORBOX);
SetErrorMode(dwMode | SEM_NOGPFAULTERRORBOX);
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&exception_handler);
_RTC_SetErrorFunc(&runtime_check_handler);
// Run your tests here
return 0;
}
In WPF application
[DllImport("kernel32.dll", SetLastError = true)]
static extern int SetErrorMode(int wMode);
[DllImport("kernel32.dll")]
static extern FilterDelegate SetUnhandledExceptionFilter(FilterDelegate lpTopLevelExceptionFilter);
public delegate bool FilterDelegate(Exception ex);
public static void DisableChashReport()
{
FilterDelegate fd = delegate(Exception ex)
{
return true;
};
SetUnhandledExceptionFilter(fd);
SetErrorMode(SetErrorMode(0) | 0x0002 );
}
You have to implement an unhandled exception filter which simply quits your application, then set that filter function with SetUnhandledExceptionFilter().
If you're using the secure CRT, you also have to provide your own invalid parameter handler and set this with _set_invalid_parameter_handler().
This blog post has some information too:
http://blog.kalmbachnet.de/?postid=75
During test you can run with a 'debugger' like ADPlus attached which can be configured in many useful ways to collect data (minidumps) on errors and yet prevent the modal dialog problems you state above.
If you want to get some useful information when your app crashes in production you can configure Microsoft Error reporting to get something similar to ADPlus data.
This isn't a direct answer to the question since this is a workaround and the question is about how to disable that feature, but in my case, I'm a user on a server with limited permissions and cannot disable the feature using one of the other answers. So, I needed a workaround. This will likely work for at least some others who end up on this question.
I used autohotkey portable and created a macro that once a minute checks to see if the popup box exists, and if it does, clicks the button to close the program. In my case, that's sufficient, and leaves the feature on for other users. It requires that I start the script when I run the at-risk program, but it works for my needs.
The script is as follows:
sleep_duration = 60000 ; how often to check, in milliseconds.
; 60000 is a full minute
Loop
{
IfWinExist, ahk_class #32770 ; use autohotkey's window spy to confirm that
; ahk_class #32770 is it for you. This seemed to be consistent
; across all errors like this on Windows Server 2008
{
ControlClick, Button2, ahk_class #32770 ; sends the click.
; Button2 is the control name and then the following
; is that window name again
}
Sleep, sleep_duration ; wait for the time set above
}
edit: A quick flag. When other things are up, this seems to attempt to activate controls in the foreground window - it's supposed to send it to the program in the background. If I find a fix, I'll edit this answer to reflect it, but for now, be cautious about using this and trying to do other work on a machine at the same time.
After trying everything else on the internet to get rid of just in time debugger, I found a simple way that actually worked and I hope will help someone else.
Go to Control Panel
Go to Administrative Tools
Go to Services
Look down the list for Machine Debug Manager
Right Click on it and click on Properties
Under the General Tab, look for Start Up Type
Click on Disable.
Click on Apply and OK.
I haven't seen the debugger message since, and my computer is running perfectly.
Instead of changing values in the registry you can completly disable the error reporting on Windows Server 2008 R2, Windows Server 2012 and Windows 8 with: serverWerOptin /disable
https://technet.microsoft.com/en-us/library/hh875648(v=ws.11).aspx