How to prevent modules from getting attached to my application process? C# - c#

For Example: I have installed an application called "RivaTuner Statistics Server v6.6.0" which has made for gamers to show FPS mark on games, since WPF apps are using DirectX, this program attaches a module to my WPF app by mistake which makes it crash (without giving any exceptions) before my app gets loaded, and when I close that program, my app works just fine!
I've fixed this problem by setting RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly
I also have the same problem with BitDefender antivirus, my program is a VPN Connection software that uses Proxifier app to set global proxy.. When my app begins to start Proxifier process, my app crashes without any exceptions.. by the way BitDefender doesn't detect Proxifier or my app as a virus or threat, it just makes my app crash and Proxifier continues to work without any problem. (Which whitelisting my app got the problem solved).
What I want to know generally, is there any way to prevent DLL injection or stopping it after it attached?
Here is the provided information by EventViewer:
Version=1
EventType=APPCRASH
EventTime=131414331835897163
ReportType=2
Consent=1
UploadTime=131414331849773927
ReportStatus=393
ReportIdentifier=c52be1e0-6378-4555-bddc-cd49f22e98d4
IntegratorReportIdentifier=e415e187-7b4d-4689-92a7-5522957c6300
Wow64Host=34404
NsAppName=TurboVPN.exe
AppSessionGuid=000037d0-0001-0015-6d89-3176a3e0d201
TargetAppId=W:00065bd30e4a6caee77eb9ec126f39eeb11200000000!000072443a77ce17608085aa75f649187cf7129fd9a8!TurboVPN.exe
TargetAppVer=2017//06//08:20:58:47!0!TurboVPN.exe
BootId=4294967295
TargetAsId=3395
Response.BucketId=c2e6858b6015d605f3dea6f209e5a680
Response.BucketTable=4
Response.LegacyBucketId=120776215139
Response.type=4
Sig[0].Name=Application Name
Sig[0].Value=TurboVPN.exe
Sig[1].Name=Application Version
Sig[1].Value=8.0.0.0
Sig[2].Name=Application Timestamp
Sig[2].Value=5939ba87
Sig[3].Name=Fault Module Name
Sig[3].Value=d3d9.dll
Sig[4].Name=Fault Module Version
Sig[4].Value=10.0.15063.0
Sig[5].Name=Fault Module Timestamp
Sig[5].Value=631de416
Sig[6].Name=Exception Code
Sig[6].Value=c0000005
Sig[7].Name=Exception Offset
Sig[7].Value=000000000000fd0c
DynamicSig[1].Name=OS Version
DynamicSig[1].Value=10.0.15063.2.0.0.256.4
DynamicSig[2].Name=Locale ID
DynamicSig[2].Value=1033
DynamicSig[22].Name=Additional Information 1
DynamicSig[22].Value=9b4f
DynamicSig[23].Name=Additional Information 2
DynamicSig[23].Value=9b4f78d83ca7cfa07fe4d1531372a428
DynamicSig[24].Name=Additional Information 3
DynamicSig[24].Value=9991
DynamicSig[25].Name=Additional Information 4
DynamicSig[25].Value=99915f8f3f68939dc06e64d116ece58a
UI[2]=C:\Users\Mr\Documents\Visual Studio 2015\Projects\TurboVPN\TurboVPN\bin\Release\TurboVPN.exe
UI[3]=TurboVPN has stopped working
UI[4]=Windows can check online for a solution to the problem.
UI[5]=Check online for a solution and close the program
UI[6]=Check online for a solution later and close the program
UI[7]=Close the program
LoadedModule[0]=C:\Users\Mr\Documents\Visual Studio 2015\Projects\TurboVPN\TurboVPN\bin\Release\TurboVPN.exe
LoadedModule[1]=C:\WINDOWS\SYSTEM32\ntdll.dll
LoadedModule[2]=C:\WINDOWS\SYSTEM32\MSCOREE.DLL
LoadedModule[3]=C:\WINDOWS\System32\KERNEL32.dll
LoadedModule[4]=C:\WINDOWS\System32\KERNELBASE.dll
LoadedModule[5]=C:\Program Files\Bitdefender\Bitdefender 2017\Active Virus Control\Avc3_00125_004\avcuf64.dll
LoadedModule[6]=C:\WINDOWS\SYSTEM32\apphelp.dll
LoadedModule[7]=C:\WINDOWS\System32\ADVAPI32.dll
LoadedModule[8]=C:\WINDOWS\System32\msvcrt.dll
LoadedModule[9]=C:\WINDOWS\System32\sechost.dll
LoadedModule[10]=C:\WINDOWS\System32\RPCRT4.dll
LoadedModule[11]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\mscoreei.dll
LoadedModule[12]=C:\WINDOWS\System32\SHLWAPI.dll
LoadedModule[13]=C:\WINDOWS\System32\combase.dll
LoadedModule[14]=C:\WINDOWS\System32\ucrtbase.dll
LoadedModule[15]=C:\WINDOWS\System32\bcryptPrimitives.dll
LoadedModule[16]=C:\WINDOWS\System32\GDI32.dll
LoadedModule[17]=C:\WINDOWS\System32\gdi32full.dll
LoadedModule[18]=C:\WINDOWS\System32\msvcp_win.dll
LoadedModule[19]=C:\WINDOWS\System32\USER32.dll
LoadedModule[20]=C:\WINDOWS\System32\win32u.dll
LoadedModule[21]=C:\WINDOWS\System32\IMM32.DLL
LoadedModule[22]=C:\WINDOWS\System32\kernel.appcore.dll
LoadedModule[23]=C:\WINDOWS\SYSTEM32\VERSION.dll
LoadedModule[24]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
LoadedModule[25]=C:\WINDOWS\SYSTEM32\MSVCR120_CLR0400.dll
LoadedModule[26]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\mscorlib\59ea37125345a946fbfb8868aa11ed27\mscorlib.ni.dll
LoadedModule[27]=C:\WINDOWS\System32\ole32.dll
LoadedModule[28]=C:\WINDOWS\system32\uxtheme.dll
LoadedModule[29]=C:\Program Files (x86)\RivaTuner Statistics Server\RTSSHooks64.dll
LoadedModule[30]=C:\WINDOWS\SYSTEM32\WINMM.dll
LoadedModule[31]=C:\WINDOWS\WinSxS\amd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9279_none_08e667efa83ba076\MSVCR90.dll
LoadedModule[32]=C:\WINDOWS\SYSTEM32\WINMMBASE.dll
LoadedModule[33]=C:\WINDOWS\System32\cfgmgr32.dll
LoadedModule[34]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System\4b4b69a2aa9b596c8b8e7a32267eac35\System.ni.dll
LoadedModule[35]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Core\d4035216edd875be919d339859343a6c\System.Core.ni.dll
LoadedModule[36]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\WindowsBase\d6053a0b7badab04868dc6e51ab4c02e\WindowsBase.ni.dll
LoadedModule[37]=C:\WINDOWS\SYSTEM32\CRYPTSP.dll
LoadedModule[38]=C:\WINDOWS\system32\rsaenh.dll
LoadedModule[39]=C:\WINDOWS\SYSTEM32\bcrypt.dll
LoadedModule[40]=C:\WINDOWS\SYSTEM32\CRYPTBASE.dll
LoadedModule[41]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\PresentationCore\b5bfbcf78210cf783ff665fea098ebfa\PresentationCore.ni.dll
LoadedModule[42]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\Presentatio5ae0f00f#\73dece296df0b44862aa59e1f73825c3\PresentationFramework.ni.dll
LoadedModule[43]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Xaml\44f34f029c456762dba3d085d6b9fa9c\System.Xaml.ni.dll
LoadedModule[44]=C:\WINDOWS\SYSTEM32\dwrite.dll
LoadedModule[45]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF\wpfgfx_v0400.dll
LoadedModule[46]=C:\WINDOWS\System32\OLEAUT32.dll
LoadedModule[47]=C:\WINDOWS\SYSTEM32\MSVCP120_CLR0400.dll
LoadedModule[48]=C:\WINDOWS\SYSTEM32\D3DCOMPILER_47.dll
LoadedModule[49]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF\PresentationNative_v0400.dll
LoadedModule[50]=C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clrjit.dll
LoadedModule[51]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Configuration\9f298b9fdf9d3d88c051ba8d0cfcdd98\System.Configuration.ni.dll
LoadedModule[52]=C:\WINDOWS\SYSTEM32\urlmon.dll
LoadedModule[53]=C:\WINDOWS\System32\shcore.dll
LoadedModule[54]=C:\WINDOWS\System32\windows.storage.dll
LoadedModule[55]=C:\WINDOWS\System32\powrprof.dll
LoadedModule[56]=C:\WINDOWS\System32\profapi.dll
LoadedModule[57]=C:\WINDOWS\SYSTEM32\iertutil.dll
LoadedModule[58]=C:\WINDOWS\SYSTEM32\SspiCli.dll
LoadedModule[59]=C:\WINDOWS\SYSTEM32\msiso.dll
LoadedModule[60]=C:\WINDOWS\SYSTEM32\PROPSYS.dll
LoadedModule[61]=C:\WINDOWS\System32\shell32.dll
LoadedModule[62]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Xml\246b8fa70f43db970414bb4119fe629f\System.Xml.ni.dll
LoadedModule[63]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Runt73a1fc9d#\9ed83e5a61548d2d78bc4b7a667e9139\System.Runtime.Remoting.ni.dll
LoadedModule[64]=C:\WINDOWS\System32\ws2_32.dll
LoadedModule[65]=C:\WINDOWS\system32\mswsock.dll
LoadedModule[66]=C:\WINDOWS\system32\dwmapi.dll
LoadedModule[67]=C:\WINDOWS\System32\MSCTF.dll
LoadedModule[68]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Drawing\763d0ca89a77cfd983874efe156a9296\System.Drawing.ni.dll
LoadedModule[69]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Windows.Forms\d63d7f874bb64e51ee0ef09cc99218f6\System.Windows.Forms.ni.dll
LoadedModule[70]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\System.Security\35f9d2604274a3e8fbf814e10789dc51\System.Security.ni.dll
LoadedModule[71]=C:\WINDOWS\System32\crypt32.dll
LoadedModule[72]=C:\WINDOWS\System32\MSASN1.dll
LoadedModule[73]=C:\WINDOWS\SYSTEM32\DPAPI.dll
LoadedModule[74]=C:\WINDOWS\SYSTEM32\WindowsCodecs.dll
LoadedModule[75]=C:\WINDOWS\SYSTEM32\d3d9.dll
LoadedModule[76]=C:\WINDOWS\SYSTEM32\igdumdim64.dll
LoadedModule[77]=C:\WINDOWS\System32\SETUPAPI.dll
LoadedModule[78]=C:\WINDOWS\assembly\NativeImages_v4.0.30319_64\Presentatioaec034ca#\248dd0bba3037acdc2ab60513b34c3f2\PresentationFramework.Aero2.ni.dll
LoadedModule[79]=C:\WINDOWS\SYSTEM32\WtsApi32.dll
LoadedModule[80]=C:\WINDOWS\SYSTEM32\WINSTA.dll
LoadedModule[81]=C:\WINDOWS\System32\clbcatq.dll
LoadedModule[82]=C:\WINDOWS\system32\dataexchange.dll
LoadedModule[83]=C:\WINDOWS\system32\d3d11.dll
LoadedModule[84]=C:\WINDOWS\system32\dcomp.dll
LoadedModule[85]=C:\WINDOWS\system32\dxgi.dll
LoadedModule[86]=C:\WINDOWS\system32\twinapi.appcore.dll
LoadedModule[87]=C:\WINDOWS\SYSTEM32\igdusc64.dll
State[0].Key=Transport.DoneStage1
State[0].Value=1
File[0].CabName=Report.zip
File[0].Path=Report.zip
File[0].Flags=196608
File[0].Type=11
File[0].Original.Path=\\?\C:\WINDOWS\system32\Report.zip
FriendlyEventName=Stopped working
ConsentKey=APPCRASH
AppName=TurboVPN
AppPath=C:\Users\Mr\Documents\Visual Studio 2015\Projects\TurboVPN\TurboVPN\bin\Release\TurboVPN.exe
NsPartner=windows
NsGroup=windows8
ApplicationIdentity=ED5A83A5552697FBE579A0CAAEF2FF9E
MetadataHash=1411986728
If you take a look, you can see the attached module LoadedModule[29]=C:\Program Files (x86)\RivaTuner Statistics Server\RTSSHooks64.dll

Preventing the DLL injection technique that this software uses completely defeats the point of using it. It has to do this, the only way it can wire itself into the DirectX render pipeline to display the statistics. That this ends up poorly and crashes your program with a completely undiagnosable AccessViolationException is quite normal. It takes just one change in an internal function that is not part of the documented API, the kind that the utility has to "hook", and the show is over.
It could be fixable, but that has to be done by the author of this utility. It is just one guy, a Russian master-hacker. Hard to get in touch with, his life can't possibly easy lately with Win10 updates arriving at a high rate these days.
You need to consider getting ahead by uninstalling it. There are other ways to accomplish the same thing, ways that are much less brittle, supported and dedicated to WPF. Use the WPF Performance Suite.

AFAIK, there are quite a few ways of preventing other processes to attach to your process.
Basically, there are two well-known approaches to attach to external process:
Debugging the external process
Injecting a thread to that process
you can overcome the first method by implementing one of anti-debug methods(There are a lot of these methods on the internet. An example would be to debug your own process )
To prevent other processes to inject thread to your process, you can set some hooks on CreateRemoteThread or LoadLibrary and initiate a procedure before they attach to your process.

Did you tried to catch exceptions during the initializecomponents function? Since this happens during the window drawing, you can try this:
public MainWindow()
{
try{
InitializeComponent();
//you remaining code
}
catch(Exception ex){
Console.Out.Writeline(ex.Message);
}
}
Also, you can try to subscribe to _Application.DispatcherUnhandledException_ and _AppDomain.CurrentDomain.UnhandledException_ that can give you more info about the application crash exception.

Related

The new Input System doesn't trigger anything anymore

This post is shamelessly a copy/paste from my post on the Unity Forums : https://forum.unity.com/threads/input-system-doesnt-trigger-anything-anymore.717386/, but Stack Overflow seems more active
TL;DR : InputSystem worked some days ago, don't trigger anything anymore, halp.
I tried the new Input System some days ago, and that's really neat ! I did a lot of stuff, trying to understand the best way to use it, and, in the end, I had a character jumping and moving everywhere, that was cool ! Then, I merged my code in our develop branch and went to bed.
Today, I want to continue my code, but my character doesn't move anymore, Actions are not triggered (even if inputs are detected in debugger) and I really don't know why. Either the code merge overwrote some important settings (I know what you're thinking and yes, the "Active Input Handling" is set on "Both" and I tried only running the preview) or I did something important during my little tests and I didn't realize.
So I decided to try to reproduce my steps on a fresh new project, maybe you guys can help me figure what do I do wrong ?
1/ Create a new 2D project (via the Hub)
2/ Install the latest Package (version 0.9.0)
3/ Click Yes on that message prompt to activate the new Input management in the settings
4/ Restart Unity Editor since it didn't restart even if the message said it would and check the project settings (yes, it's on "Both", and yes, my Scripting Runtime Version is 4.0)
5/ Create a new GameObject and add a PlayerInput on it
6/ Click on "Open Input Settings" and create an "InputSettings" asset
7/ Click on "Create Actions..." to create my ActionMap asset
8/ Create a "TestAction" on my "Player" ActionMap and set it to the key "t"
9/ Create a new Script "TestScript" that contains a OnTestAction() method (that only logs "test") and enables the test map/action (just to be sure) :
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.PlayerInput;
public class TestScript : MonoBehaviour
{
void Start()
{
InputActionMap playerActionMap = GetComponent<PlayerInput>().actions.GetActionMap("Player");
playerActionMap.Enable();
playerActionMap.GetAction("TestAction").Enable(); //Just to be sure
}
public void OnTestAction()
{
Debug.Log("test");
}
}
10/ Pressing "Play" and spamming "T" like a madman to try to display a debug (note that, in the debugger, a User is created, my "t" presses are detected, my TestAction exists and is mapped on the "t" key but no debug is displayed
It's probably a silly problem, but it's driving me crazy, what do I do wrong ? It's even more infuriating that it worked some days ago !
Additional information :
- Switching the Input Management from "Both" to "New Input System (preview) does nothing
- Checking in Update() is my action is enabled returns "True" every frame
- Checking in Update() is my action is triggered returns "False" every frame
- Using action.started/triggered/performed does nothing (I tried also switching to UnityEvent or C# events for this) :
public class TestScript : MonoBehaviour
{
InputAction a;
void Start()
{
InputActionMap playerActionMap = GetComponent<PlayerInput>().actions.GetActionMap("Player");
playerActionMap.Enable();
a = playerActionMap.GetAction("TestAction");
a.Enable(); //Just to be sure
a.started += OnTriggeredTestAction;
a.performed += OnTriggeredTestAction;
a.canceled += OnTriggeredTestAction;
}
public void OnTestAction()
{
Debug.Log("test");
}
public void OnTriggeredTestAction(InputAction.CallbackContext ctx)
{
Debug.Log("test triggered");
}
}
Injecting directly the InputActionReference of my TestAction and using it does nothing
Forcing "Default Control Scheme" and "Default Action Map" does nothing
Using BroadcastMessage or UnityEvents doesn't work
You probably tried to import a new input system package for multiple input devices compatibility. These types of errors are due to conflict between old and new input system packages and are probably resolved in the latest updates.
To resolve this issue, Go to Edit -> Project Settings->Player->Under Other Settings under Configuration is the option Active Input Handling. Select Both. Unity will restart. Now your problem should be solved. You will be able to use old input system packages and the new ones also simultaneously.
Check for rogue users in the input debugger
I was having very similar symptoms (Input System would randomly just stop sending callbacks). When I opened up the input debugger, it was registering the key presses, but the callbacks were never being called in my script.
Restarting Unity didn't help.
Rebooting didn't help.
I also discovered in the input debugger that there were 2 "users" in the input system and (by process of disabling Game Objects in the scene one at a time) discovered that I had accidentally attached another copy of my Input Action Asset to a different Game Object in the scene and that Unity was registering this other object as a 2nd player or "user", which was assigned all the input action bindings I was trying to capture.
The rogue Action Asset was essentially intercepting the actions, preventing the callbacks from being called on the intended script. I don't know if that's your particular issue, but maybe it will help someone else who (like me) has spent hours pouring through forums, looking for a solution to this elusive problem.
An easy way to tell if you have the same problem is to open the input debugger and see if the desired actions are actually mapped to the user of interest.
Screen clip of input debugger:
For me, there was an unexpected User #1 and only one of the users (not the intended one) actually had keys bound to the desired actions
Posting just incase others run into this issue, as this solved my problem. Make sure to call Enable() for it to start routing events.
//Create a and set the reference
private InputControls _inputMapping;
private void Awake() => _inputMapping = new InputControls();
//Route and Un-route events
private void OnEnable() => _inputMapping.Enable();
private void OnDisable() => _inputMapping.Disable();
I don't know if this will work for you but it worked for me and I was having the same issue.
I had created 2 control schemes. Mobile and Pc. Mobile required touch screen and PC required keyboard and Mouse. Doing this made my Mobile input event stop firing. So adding the Gamepad to my Mobile Control scheme allowed the events to fire again.
TLDR. Check your control scheme make sure it allows for the inputs your binding to.
I had a similar problem, reproduced with exactly the steps described in the question.
In my case, I forgot to set control schemes.
The problem was fixed after adding them.
To do so:
Open your Input Action Asset.
Select a control scheme, in the upper left corner. (say, Keyboard) (if you haven't added a control scheme to begin with, your problem may be different than mine)
Go Right Click > Edit Control Scheme.
EditControlScehme Screen Img
Click on the plus sign to add a control scheme to the list.
Add control scheme to the list Screen Img
Select the control scheme you want to add. (in this case, Keyboard)
Select control scheme Screen Img
Should look like this:
Added control scheme Screen Img
You're all set. Save everything and the problem should be fixed.
Play your game and it should work.
As of at least Unity 2020.1.2 and Input System 1.0.0 the input system will randomly stop working correctly. The only fix I'm aware of is restarting Unity.

0xC000027B exception in store UWP app (Windows.UI.XAML)

I've an C#/UWP-app in beta-release in the Microsoft App-Store. Most of the users have no problems with the App, but for one user the app is crashing on startup. You can't even see the Splash-Screen (it should be displaying a logo or color, however it is white).
In the eventlog this genreic event is logged:
0xc000027b (Windows.UI.XAML)
The only difference is, that his Windows-10 Build differs from the other users (10.0.10240 vs 10.0.10586). However, I've collected the crashdumps ("minidumps") and tried to follow this tutorial.
If i try this command:
dt <Parameter[0]> combase!_STOWED_EXCEPTION_INFORMATION_HEADER*
Windbg gives me this:
Memory read error (at Parameter[0])
Actually I've integrated the hockey-sdk for automatic crash-reports, but it doesn't report me that specific crash in the dashboard.
How can I trace down this crash?
Update:
I've managed to get the Call-Stack with PDE:
Windows_UI_Xaml!DirectUI::PropertyPathListener::GetValue+0x3e
Windows_UI_Xaml!DirectUI::BindingExpression::GetValue+0xbb
Windows_UI_Xaml!DirectUI::DependencyObject::SetValueExpression+0x24b
Windows_UI_Xaml!DirectUI::DependencyObject::SetBindingCore+0x56
Windows_UI_Xaml!DirectUI::DependencyObject::SetBindingCallback+0x146
Windows_UI_Xaml!CBinding::SetBinding+0x48
Windows_UI_Xaml!XamlNativeRuntime::SetValue+0x4c2
Windows_UI_Xaml!BinaryFormatObjectWriter::SetValueOnCurrentInstance+0x1ad
Windows_UI_Xaml!BinaryFormatObjectWriter::WriteNode+0x144a
Windows_UI_Xaml!CTemplateContent::LoadXbfVersion2+0xd1
Windows_UI_Xaml!CTemplateContent::Load+0x4d
Windows_UI_Xaml!CFrameworkTemplate::LoadContent+0x270
Windows_UI_Xaml!CControlTemplate::LoadContent+0x18
Windows_UI_Xaml!CFrameworkElement::ApplyTemplate+0x30a
Windows_UI_Xaml!CContentControl::ApplyTemplate+0x20
Windows_UI_Xaml!CFrameworkElement::InvokeApplyTemplate+0x17f
Windows_UI_Xaml!CFrameworkElement::MeasureCore+0x2a3
Windows_UI_Xaml!CUIElement::MeasureInternal+0x1cb
Windows_UI_Xaml!CUIElement::Measure+0x598
Windows_UI_Xaml!CGrid::MeasureOverride+0x307
Windows_UI_Xaml!CFrameworkElement::MeasureCore+0x707
Windows_UI_Xaml!CUIElement::MeasureInternal+0x1cb
Windows_UI_Xaml!CUIElement::Measure+0x598
Windows_UI_Xaml!CGrid::MeasureOverride+0x307
Windows_UI_Xaml!CFrameworkElement::MeasureCore+0x707
This would mean, that I've somewhere an incorrect binding?

Intercept MS Windows 'SendTo' menu calls?

SCENARIO
I manage and organize many files during the day, the SendTo is the most used feature that I use on Windows.
PROBLEM
By default, when the user clicks an item/link of the contextmenu to send the files, the O.S does not show any kind of advise/notifier indicating that the files are copying to the selected destination.
I consider it a very wrong design issue because for big files its OK ...a progressbar will be shown, but if the files are to small it will not show any progressbar/visual indicator so is not possible to ensure that the files are copied (without manual effort) because I'm human and I could click outside the SendTo contextmenu by error.
So, I would like to develop a personal mini-tool that will help me to optimize my time showing me a notifier window wherever on the screen when I send/copy files using the SendTo feature from the contextmenu, and only the SendTo feature.
QUESTION
In just simple words, I want to detect a copy/send operation from SendTo menu to ensure that the click was done properly on the menu item (and not outside the menu), by also providing additional basic info such as the source folder, the destination folder, and the amount of files or the filepaths.
Any ideas to start developing this tool in the right direction?.
I will be grateful for a code example in C# or else VB.Net, preferably this last.
APPROACH
Since I don't know how to start doing this I mean which could be the easiest or the efficient way to intercept those SendTo calls, firstly I thought to hook the CopyFile or CopyFileEx API functions, but they do not provide the information that I need because that function will be called in any kind of copy operation and not only when I use the SendTo Feature, so I'm lost.
I'm not sure if I should investigate more about internal calls, or maybe investigate more about the windows contextmenu itself instead of messing with function hooks and ugly things that I could avoid.
My main idea is to develop a hidden WinForms (or else a windows service) that stays in background waiting for when I use the SendTo feature (when I click on an item of the SendTo menu) and then show any kind of visual indicator on the screen to ensure that I properly clicked that menu-item and maybe inform about the amount of files that I'm moving and where I'm moving them.
RESEARCH
Here is a code example that I think it demostrates how to instantiate the SendTo com object to create your own?, but its written in c++ and I'm not sure if the example is helpful because my intention is not to replace the SendTo menu but I'll keep this useful info here it it serves for something else:
How to add(enable) standard "Send To" context menu option in a namespace extension
The KNOWNFOLDERID constants docs gives some useful info about the SendTo folder, again I'm not sure if this could help maybe for a read/access monitoring approach?, I just keep the info here:
GUID: {8983036C-27C0-404B-8F08-102D10DCFD74}
Default Path: %APPDATA%\Microsoft\Windows\SendTo
Legacy Default Path: %USERPROFILE%\SendTo
In the Shell Extension Handlers docs there is a Copy hook handler which I don't know if it has relation with the SendTo's COM component and if that could help me in some way,
the same ignorance for IContextMenu::InvokeCommand method reference which maybe I could intercept it to identify a SendTo invocation?
By the moment I feel like flying blind.
I recently found this A managed "Send To" menu class but again its a example written in C/C++ (I think is the same source before) which I don't understand at all and again I'm not sure if that could help me because I repeat that replacing SendTo is not what I have in mind (just because I don't know how to properly do it avoiding all possible risks, I prefer to still let Windows logic copy/send the files, I just want to detect the copy operation to retrieve info)
EXPECTED RESULTS AND USAGE
Step 1:
Select a random file and use the SendTo menu (in my language, Spanish, the command name is 'Enviar a')
Step 2:
Let the .net application's logic (working in background) intercept the SendTo operation to retrieve info.
(I only need help with this step)
Step 3:
Display the info somewhere over the screen to ensure that the SendTo operation was performed, to ensure that I properly clicked the SendTo item (My Link).
(That popup is just a simulation, I don't know any way to retrieve all that info)
It's really simple to do once you understand what SendTo really does, and it doesn't involves COM or shell extensions at all. Basically, the send to menu is populated with the content of the SendTo folder of the user profile (C:\Users\\AppData\Roaming\Microsoft\Windows\SendTo by default in Windows 6.x).
When clicked, if the option is a shortcut to a folder it will copy the files there, but if there is a shortcut to a program (or a program executable itself) it will run that program, passing the paths of the selected files as command-line arguments.
From there, it's really trivial to make some program that simply takes paths as arguments, present some kind of notification and then copies the files or do whatever you want with them.
A quick and dirty example could be as follow (in C#, but could be done with anything else really):
private static void Main(string[] args)
{
if(MessageBox.Show("Are you sure you want to copy files?", "Copy files", MessageBoxButtons.YesNo) == DialogResult.No) return;
foreach (string file in args)
File.Copy(file, Path.Combine("c:\\temp", Path.GetFileName(file));
}
This just ask for confirmation for copying a bunch of files. Note that this really doesn't "intercepts" the send to menu, but rather handles it completely, so it's the program responsability to do any meaningful action. A more serious implementation could use the built-in Windows copy dialog and display some screen with progress or anything else, that's up to your needs.
It could also take some more parameters on the command line. When you place a shortcut in the SendTo folder, the destination could add some more parameters that will be passed as the first ones (before the file names). For example the destination of the shortcut can read c:\program files\copyfiles.exe c:\temp to pass the destination folder instead of hardcoding. The called program must then interpret the first parameter as the destination path and subsequent ones as the source files.
I've had to do something like this before. You don't even have to intercept the SendTo() function, you only need to make sure the the file has arrived. How about FileSystemWatcher if it's on the same computer?
You could use a watcher to watch before you send it, then, if the file successfully arrives at it's destination, you can display a successful message, and then kill the watcher.
Code Example
// Create a FileSystemWatcher property.
FileSystemWatcher fsw { get; set; }
// So we can set the FileToWatch within WatchFilesBeforeTransfer().
private string FileToWatch { get; set; }
private void WatchFilesBeforeTransfer(string FileName, string DestinationFolder)
{
fsw = new FileSystemWatcher();
fsw.Path = DestinationFolder;
FileToWatch = FileName;
// Only if you need support for multiple directories. Code example note included.
fsw.InclueSubdirectories = true;
// We'll be searching for the file name and directory.
fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName
// If it's simply moving the file to another location on the computer.
fsw.Renamed += new RenamedEventHandler(FileRenamed);
// If it was copied, not moved or renamed.
fsw.Created += new FileSystemEventHandler(FileCreated);
fsw.EnableRaisingEvents = true;
}
// If the file is just renamed. (Move/Rename)
private void FileRenamed(Object source, RenamedEventArgs e)
{
// Do something.
// Note that the full filename is accessed by e.FullPath.
if (e.Name == FileToWatch)
{
DisplaySuccessfulMessage(e.Name);
KillFileWatcher();
}
}
// If creating a new file. (Copied)
private void FileCreated(Object source, FileSystemEventArgs e)
{
// Do something.
// Note that the full filename is accessed by e.FullPath.
if (e.Name == FileToWatch)
{
DisplaySuccessfulMessage(e.Name);
KillFileWatcher();
}
}
private void KillFileWatcher()
{
fsw.Dispose();
}
You can access the desired property information (like in your popup gif) in this way:
Folder name: Path.GetDirectory(e.FullPath); (like "C:\yo\")
Full file name: e.FullPath (like "C:\yo\hey.exe")
File name: e.Name (like "hey.exe")
Non-code execution process:
Before you initiate SendTo(), create an instance of the FileSystemWatcher property, and have it watch for a specific Folder/File name combination, which should show up in the watched folder: WatchFilesBeforeTransfer(FileName, DestinationFolder).
Initiate SendTo().
File received? DisplaySuccessfulSendToMessage(), KillFileWatcher();
???
Profit.
UPDATE:
I just realized that's just for one file. If you want to check for multiple files, you could either create multiple FileWatcher instances (not recommended), or use a List<string> object, like this:
private void SendTo(List<string> FileCollection)
{
// Clear your previous FileList.
FileList.Clear();
foreach (string file in FileCollection)
{
FileList.Add(file);
}
// Rest of the code.
}
List<string> FileList { get; set; }
private void WatchFilesBeforeTransfer(string DestinationFolder)
{
// Same code as before, but delete FileToWatch.
}
private void FileRenamed(Object source, RenamedEventArgs e)
{
foreach (string file in FileList)
{
if (e.Name == file)
{
// Do stuff.
}
}
}
private void FileCreated(Object source, FileSystemEventArgs e)
{
foreach (string file in FileList)
{
if (e.Name == file)
{
// Do stuff.
}
}
}
Hope this helps!
I'm afraid this ain't that easy.
I was playing around with the FileSystemWatcher on this, but with only partly success.
Something that should definitely work are File system drivers but this looks like just too, well, look at it...
In the end it might be the easiest way to write your own shell extension to access the SendTo folder, and use this instead of the SentTo command which would give you full control.
These might be some starters:
Windows shell extensions
Shell Context Menus
Maybe I come a little bit late to answer my own question, which was published on year 2015, but it wasn't until few days ago that I became interested in this matter again, with much more experience and knowledge gained in .NET after these years to start from scratch and try to understand everything that I did not understood in the past.
I just discovered that, as #Ňɏssa Pøngjǣrdenlarp already commented in the comments box, apparently the most viable way to accomplish this would be to implement my own SendTo context menu and use IFileOperationProgressSink interface to report progress, which for this firstly I need to depend on the usage of IFileOperation interface.
The reason to use the IFileOperation interface is because it seems the only way offered in the Windows API to let the developer perform multiple file operations (copy, move, rename, create or delete) all at once within the same progress dialog UI. This is probably the interface used by the system when the user selects multiple files or directories (via the SendTo menu or just CTRL+C and CTRL+V) to move or copy them at once, because it only shows one progress dialog with all the copy operations queued in it...
So clearly IFileOperation and IFileOperationProgressSink interfaces were what I need. But from what I know there is no managed implementation of these interfaces in the .NET framework namespaces (neither in the Microsoft's WindowsAPICodePack library), which seems somewhat inexcusable to me considering that these interfaces exists since the era of Windows VISTA or even earlier, and it is an indisputable improvement being the totally opposite of any built-in members that you can think of to perform copy, move, rename, create or delete operations, like for example System.IO.File.Copy or Microsoft.VisualBasic.FileIO.FileSystem.CopyFile method. All of them only supports a single operation and only on a single progress dialog at once.
So I focused to investigate on that suggested solution, and I ended up finding a good implementation of IFileOperation and IFileOperationProgressSink interfaces in this repository:
https://github.com/misterhaan/au.Shared/tree/master/IO/Files.FileOperation
And this one which is the original implementation that I found on a old Microsoft's article which also comes with a good PDF reading to learn some things:
https://github.com/mlaily/MSDNMagazine2007-.NET-Matters-IFileOperation-in-Windows-Vista
https://learn.microsoft.com/en-us/archive/msdn-magazine/2007/december/net-matters-ifileoperation-in-windows-vista
Actually, for what I've discussed in this thread to do since year 2015, delving into the use of the IFileOperationProgressSink interface to report progress would not be necessary (only if I really want a deep progress information), since it is enough to determine that the copy was started / the call to IFileOperation.PerformOperations function was performed, and if any problems occur during the copy then it will appear in the progress dialog UI.
But of course what is still necessary is to develop a shell-extension of a custom SendTo menu to replace the one built into Windows. Shell-extensions could be developed with SharpShell library.
I develop in VB.NET language. I managed to extend and document their IFileOperation implementation and the wrapper, and updated the enums adding the newer, missing values added for Windows 7 and Windows 8.
If it can be helpful for someone, I'm going to attach the IFIleOperation and the wrapper in Vb.NET all in a new answer (because it exceeds the maximum character limit allowed for a post).
Note that in my implementation of IFileOperation interface and the wrapper class with name FileSystemOperation you will find some return types and missing classes or methods (like HRESULT return type or NativeMethods class), I just can't share all in one place, but these missing things are things that any experienced programmer will know how to resolve (eg. change HRESULT to UInteger type, and go to Pinvoke.net to find any missing method from my NativeMethods class).
UPDATE
It seems that StackOverflow doesn't allow me to add another answer, so I'll upload my implementation on PasteBin instead:
Class FileSystemOperation
https://pastebin.com/nvgLWEXu
Interface IFileOperation
https://pastebin.com/GzammHtu
Interface IFileOperationProgressSink
https://pastebin.com/jf9JjzyH
Class ComObjectDisposer(Of T As Class)
https://pastebin.com/7mPeawWr
Enum TransferSourceFlags
https://pastebin.com/V7wSSEvv
Enum FileOperationFlags
https://pastebin.com/A223w9XY
That's all.

Failed to perform action on hidden control exception

I am trying to create a UI test in VS 2010 using IE 9 in IE 8 compatibilty mode however when trying to record an action recording many of the steps fail. Then when I manually code in the missing steps and try to fill in a log in form with a username and password I get an exception that says I have failed to perform an action on hidden control.
The UI Test code:
public void Recordedmethod()
{
BrowserWindow uILogInWindowsInternetWindow = this.UILogInWindowsInternetWindow;
HtmlHyperlink uILogInHyperlink = this.UILogInWindowsInternetWindow.UIHomePageDocument.UILogInHyperlink;
HtmlEdit uIUsernameEdit = this.UILogInWindowsInternetWindow.UILogInDocument1.UIUsernameEdit;
HtmlEdit uIPasswordEdit = this.UILogInWindowsInternetWindow.UILogInDocument1.UIPasswordEdit;
#endregion
// Go to web page 'http://localhost:15856/WebSite1/'
uILogInWindowsInternetWindow.NavigateToUrl(new System.Uri(this.RecordedMethodParams.UILogInWindowsInternetWindowUrl));
// Set flag to allow play back to continue if non-essential actions fail. (For example, if a mouse hover action fails.)
Playback.PlaybackSettings.ContinueOnError = true;
// Mouse hover 'Log In' link at (1, 1)
Mouse.Click(uILogInHyperlink);
// Reset flag to ensure that play back stops if there is an error.
Playback.PlaybackSettings.ContinueOnError = false;
// Type 'test' in 'Username:' text box
uIUsernameEdit.Text = this.RecordedMethodParams.UIUsernameEditText;
// The following element is no longer available: IE web control; Process Id [6320], window handle [3168166]
// Type '********' in 'Password:' text box
uIPasswordEdit.Password = this.RecordedMethodParams.UIPasswordEditPassword;
// The following element is no longer available: IE web control; Process Id [6320], window handle [3168166]
}
This is an issue linked to an Internet Explorer patch that was released in September.
KB2870699
This affects VS2010 and VS2012.
Microsoft released a patch that corrects the issue for VS2012 (and I've confirmed that it fixed the issue for me).
http://blogs.msdn.com/b/visualstudioalm/archive/2013/09/17/coded-ui-mtm-issues-on-internet-explorer-with-kb2870699.aspx
Currently the only workaround for VS2010 is to uninstall the patch (KB2870699); however, as with any sort of security patch you'll want to consider carefully whether pulling it is safe to do given your situation.
EDIT: This was not a fun bug for me to deal with. I had just upgraded to VS2012 from VS2010 and all of a sudden I found none of my previously functioning CodedUI tests working. I assumed it was an issue with VS2012 and after banging my head against the wall for the better part of a day I found out it was an issue with a patch. It was just my luck that I upgraded to 2012 at the same time the patch had been installed on my system. Good times!
There is actually an updated for VS 2012 to fix this issue
http://blogs.msdn.com/b/visualstudioalm/archive/2013/09/17/coded-ui-mtm-issues-on-internet-explorer-with-kb2870699.aspx
Hope this helps!
I was having the same problem with my coded ui test. It's an issue with VS-2012 i guess, i tried every update (installing/uninstalling them and everything..) nothing worked.
I tried VS-2013 Ultimate and it worked.
You can use exception handling to capture the error while still not having the test failed.
The test is failing because at the time it performs click action, the control is hidden.
try
{
//your code goes here
}
catch(FailedToPerformActionOnHiddenControlException e)
{
Console.WriteLine(e.Message);
}

16-Bit Apps running under NTVDM

I am trapping for the execution of some old 16-bit applications that our internal folks should no longer be using. They are 1985 DOS apps, so trapping for them was easy... capture any process that launches under NTVDM.exe
Now, the problem is finding out which program NTVDM is actually running under the hood. Apparently there are a coupleof the 1985 programs that they SHOULD be allowed to run, so I need to see the actual EXE name that is hiding under NTVDM.
WqlEventQuery query =
new WqlEventQuery("__InstanceCreationEvent",
new TimeSpan(0, 0, 1),
"TargetInstance isa \"Win32_Process\"");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Start();
...
static void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
ProcessInfo PI = new ProcessInfo();
PI.ProcessID = int.Parse(instance["ProcessID"].ToString());
PI.ProcessName = instance["Name"].ToString();
PI.ProcessPath = instance["ExecutablePath"].ToString();
// Here's the part I need...
PI.ActualEXE = ???;
// ... do the magic on the PI class ...
instance.Dispose();
}
When I capture the instance information, I can get the command line, but the arguments are "-f -i10" ... There is no EXE name on the command line. Is there any other method/property I should be looking at to determine the EXE name of the 16-bit application that's actually running?
UPDATE: Let me refine the question: If I can find the NTVDM process, how can I -- programatically -- know the actual path to the EXE that is being executed underneath?
Thanks.
The trick is not to use VDMEnumProcessWOW (which gives the VDMs), but to use VDMEnumTasksWOW. The enumerator function that you pass to this function will be called for each 16 bit task in the specified VDM.
I haven't checked it myself, but according to the documentation, this library of CodeProject does exactly that, if you pass in the PROC16 enum value. It's C++, if you need help compiling that code and calling it from C#, let me know and I'll give you an example.
A program that uses this technique is Process Master, it comes with full source. I suggest you run it to find out whether it gives the info you need, and if so, you can apply this method to your own application (it doesn't run on Windows Vista or 7, it uses old VB5 code, apparently it's not compatible. It should run on XP).
If things with these functions do not go as planned, you may be on Vista and may need the hotfix described in this StackOverflow question, which points to downloading a hotfix, which is in turn described here:
"An application that uses the
VDMEnumProcessWOW function to
enumerate virtual DOS machines returns
no output or incorrect output on a
computer that is running a 32-bit
version of Windows Vista"
Update: while this seems promising, I applied the patch, ran several versions of the code, including Microsoft's, and while they all work on XP, they fail silently (no error, or wrong return value) on Vista.
The "kinda" working code
Update: I experimented with (amongst others) with the following code, which compiles fine in C# (and can be written simpler, but I didn't want to run a marshal-mistake risk). When you add these functions, you can call Enum16BitProcesses, which will write the filenames of the EXE files of the 16 bit processes to the Console.
I can't run it on Vista 32 bit. But perhaps others can try and compile it, or find the error in the code. It would be nice to know whether it works on other systems:
public class YourEnumerateClass
{
public static void Enum16BitProcesses()
{
// create a delegate for the callback function
ProcessTasksExDelegate procTasksDlgt =
new ProcessTasksExDelegate(YourEnumerateClass.ProcessTasksEx);
// this part is the easy way of getting NTVDM procs
foreach (var ntvdm in Process.GetProcessesByName("ntvdm"))
{
Console.WriteLine("ntvdm id = {0}", ntvdm.Id);
int apiRet = VDMEnumTaskWOWEx(ntvdm.Id, procTasksDlgt, IntPtr.Zero);
Console.WriteLine("EnumTaskWOW returns {0}", apiRet);
}
}
// declaration of API function callback
public delegate bool ProcessTasksExDelegate(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
);
// the actual function that fails on Vista so far
[DllImport("VdmDbg.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern int VDMEnumTaskWOWEx(
int processId,
ProcessTasksExDelegate TaskEnumProc,
IntPtr lparam);
// the actual callback function, on Vista never gets called
public static bool ProcessTasksEx(
int ThreadId,
IntPtr hMod16,
IntPtr hTask16,
IntPtr ptrModName,
IntPtr ptrFileName,
IntPtr UserDefined
)
{
// using PtrToStringAnsi, based on Matt's comment, if it fails, try PtrToStringAuto
string filename = Marshal.PtrToStringAnsi(ptrFileName);
Console.WriteLine("Filename of WOW16 process: {0}", filename);
return false; // false continues enumeration
}
}
Update: Intriguing read by the renown Matt Pietrek. Mind the sentence, somewhere near the end:
"For starters, MS-DOS-based programs
seem to always run in separate NTVDM
sessions. I was never able to get an
MS-DOS-based program to run in the
same session as a 16-bit Windows-based
program. Nor was I able to get two
independently started MS-DOS-based
programs to run in the same NTVDM
session. In fact, NTVDM sessions
running MS-DOS programs don't show up
in VDMEnumProcessWOW enumerations."
Seems that, to find out what processes are loaded, you'll need to write a hook into NTVDM or write a listener that monitors access to the file. When the application that tries to read a certain DOS file is NTVDM.exe, it's bingo. You may want to write a DLL that's only attached to NTVDM.exe, but now we're getting a bit ahead of ourselves. Long story short: this little ride into NTVDM has shown "possibilities" that appeared real hoaxes in the end.
There's one other way, but time is too short to create an example. You can poke around in the DOS memory segments and the EXE is usually loaded at the same segment. But I'm unsure if that eventually will lead to the same result and whether it's worth the effort.
This works for me:
Follow the instructions at Description of the Software Restriction Policies in Windows XP to open the local or domain policy editor.
Under Software Restriction Policies -> Additional Rules, right click and select New Hash Rule.
Browse to (for example) edit.com. Make sure Security Level is set to Disallowed. Click OK.
Now,
C:\>edit
The system cannot execute the specified program.
(I get the same results from command.com and cmd.exe -- under Win XP)
From this link about VDMDBG functions, you may be able to P/Invoke "VDMEnumProcessWOW()", then enumerate modules within the process using PSAPI.
Note Regarding 16-bit DOS Applications:
None of the VDMDBG functions work with
16-bit DOS applications. To enumerate
DOS VDMs, you need to use another
method. First, you could use
VDMEnumProcessWOW() to make a list of
all Win16 VDMs, and then enumerate all
instances of NTVDM.exe using some
other scheme (such as PSAPI). Any
NTVDM.exe from the full enumeration
that was not in the Win16 list is a
DOS VDM. You can create and terminate
16-bit DOS applications with
CreateProcess() and
TerminateProcess().
Hope that helps...

Categories