I am trying to write a program that will hook into application startup and capture the commandline. Don't have an idea where to start as I am pretty green in windows programming.
Would appreciate any help
thanks
You didn't mention your prefered programming language, so I'll use C# for example snippets.
You can start a process and capture/write into its standard IO streams.
The following snippet, opens a process and captures its StdOut stream:
using (var process = Process.Start(new ProcessStartInfo(FileName = #"yourExecutablePath", UseShellExecute = false, RedirectStandardOutput = true)))
using (var stdout = process.StandardOutput)
Console.WriteLine(stdout.ReadToEnd());
EDIT 1
Looks like you want to hook Windows APIs like CreateProcess.
One way to do so is to write a kernel driver and use hooking techniques such as SSTD patching. But writing a kernel driver IMO is cumbersome.
In some cases you can use user-level hooks. There are a few libraries that might help you with that, including: EasyHook, Deviare, and MS Detour.
EDIT 2
You can also use WMI as #David Heffernan suggested but it will only notify you AFTER the process gets started (as opposed to hooking, which allows you to run some arbitrary code BEFORE the hooked function gets called and/or override the function call):
using System.Management;
// Run this in another thread and make sure the event watcher gets disposed before exit
var start = new ManagementEventWatcher(new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
start.EventArrived += new EventArrivedEventHandler(delegate (object sender, EventArrivedEventArgs e) {
console.WriteLine("Name: {0}, Command Line: {1}", e.NewEvent.Properties["ProcessName"].Value, e.NewEvent.Properties["Commandline"].Value);
});
start.Start()
Related
I’m trying to write some Rust code that uses Windows.Web.UI.Interop.WebViewControl (which is a Universal Windows Platform out-of-process wrapper expressly designed so Win32 apps can use EdgeHTML), and it’s all compiling, but not working properly at runtime.
The relevant code boils down to this, using the winit, winapi and winrt crates:
use winit::os::windows::WindowExt;
use winit::{EventsLoop, WindowBuilder};
use winapi::winrt::roapi::{RoInitialize, RO_INIT_SINGLETHREADED};
use winapi::shared::winerror::S_OK;
use winrt::{RtDefaultConstructible, RtAsyncOperation};
use winrt::windows::foundation::Rect;
use winrt::windows::web::ui::interop::WebViewControlProcess;
fn main() {
assert!(unsafe { RoInitialize(RO_INIT_SINGLETHREADED) } == S_OK);
let mut events_loop = EventsLoop::new();
let window = WindowBuilder::new()
.build(&events_loop)
.unwrap();
WebViewControlProcess::new()
.create_web_view_control_async(
window.get_hwnd() as usize as i64,
Rect {
X: 0.0,
Y: 0.0,
Width: 800.0,
Height: 600.0,
},
)
.expect("Creation call failed")
.blocking_get()
.expect("Creation async task failed")
.expect("Creation produced None");
}
The WebViewControlProcess instantiation works, and the CreateWebViewControlAsync function does seem to care about the value it received as host_window_handle (pass it 0, or one off from the actual HWND value, and it complains). Yet the IAsyncOperation stays determinedly at AsyncStatus.Started (0), and so the blocking_get() call hangs indefinitely.
A full, runnable demonstration of the issue (with a bit more instrumentation).
I get the feeling that the WebViewControlProcess is at fault: its ProcessId is stuck at 0, and it doesn’t look to have spawned any subprocess. The ProcessExited event does not seem to be being fired (I attached something to it immediately after instantiation, is there opportunity for it to be fired before that?). Calling Terminate() fails as one might expect in such a situation, E_FAIL.
Have I missed some sort of initialization for using Windows.Web.UI.Interop? Or is there some other reason why it’s not working?
It turned out that the problem was threading-related: the winit crate was doing its event loop in a different thread, and I did not realise this; I had erroneously assumed winit to be a harmless abstraction, which it turned out not quite to be.
I discovered this when I tried minimising and porting a known-functioning C++ example, this time doing all the Win32 API calls manually rather than using winit, so that the translation was correct. I got it to work, and discovered this:
The IAsyncOperation is fulfilled in the event loop, deep inside a DispatchMessageW call. That is when the Completion handler is called. Thus, for the operation to complete, you must run an event loop on the same thread. (An event loop on another thread doesn’t do anything.) Otherwise, it stays in the Started state.
Fortunately, winit is already moving to a new event loop which operates in the same thread, with the Windows implementation having landed a few days ago; when I migrated my code to use the eventloop-2.0 branch of winit, and to using the Completed handler instead of blocking_get(), it all started working.
I shall clarify about the winrt crate’s blocking_get() call which would normally be the obvious solution while prototyping: you can’t use it in this case because it causes deadlock, since it blocks until the IAsyncOperation completes, but the IAsyncOperation will not complete until you process messages in the event loop (DispatchMessageW), which will never happen because you’re blocking the thread.
Try to initialize WebViewProcessControl with winrt::init_apartment(); And it may needs a single-threaded apartment(according to the this answer).
More attention on Microsoft Edge Developer Guide:
Lastly, power users might notice the apppearance of the Desktop App
Web Viewer (previously named Win32WebViewHost), an internal system app
representing the Win32 WebView, in the following places:
● In the Windows 10 Action Center. The source of these notifications
should be understood as from a WebView hosted from a Win32 app.
● In the device access settings UI
(Settings->Privacy->Camera/Location/Microphone). Disabling any of
these settings denies access from all WebViews hosted in Win32 apps.
So here is my situtation.
I am using the Windows OS. I am running a Matlab GUI that launches another executable at startup. The other executable runs in batch mode (runs in cmd in the background).
I want to make it so when a user clicks a button on the Matlab GUI, the other executable will run a command and remain open. Is this possible?
NOTE: I do not want to open a new cmd window, I want the existing one to execute commands.
Unfortunately it does not appear that Matlab has the ability you are looking for, at least not directly. I found a post which does explain how to do it with the help of .NET though, which is fortunate since you are on the Windows platform: http://www.mathworks.com/matlabcentral/answers/72356-using-matlab-to-send-strings-to-the-stdin-of-another-console-application
I have copied a lot of this from that post
function lh = task()
% Initialize the process and its StartInfo properties.
% The sort command is a console application that
% reads and sorts text input.
process = System.Diagnostics.Process;
process.StartInfo.FileName = 'sort.exe';
process.EnableRaisingEvents = true;
process.StartInfo.CreateNoWindow = true;
% Set UseShellExecute to false for redirection.
process.StartInfo.UseShellExecute = false;
%Redirect the standard output of the sort command.
process.StartInfo.RedirectStandardOutput = true;
% Set our event handler to asynchronously read the sort output.
lh = process.addlistener('OutputDataReceived',#sortOutputHandler);
% Redirect standard input as well. This stream
% is used synchronously.
process.StartInfo.RedirectStandardInput =true;
% Start the process.
process.Start();
%Use a stream writer to synchronously write the sort input.
ProcessStreamWriter = process.StandardInput;
% Start the asynchronous read of the sort output stream.
process.BeginOutputReadLine();
%Prompt the user for 4 input text lines. Write each
%line to the redirected input stream of the sort command.
numInputLines = 0;
while(numInputLines ~= 4)
inputText = input('Enter a text line (or press the Enter key to stop):', 's');
numInputLines = numInputLines + 1;
if(~isempty(inputText))
ProcessStreamWriter.WriteLine(inputText);
end
end
disp('end of input stream');
%end the inputr stream to the sort command
ProcessStreamWriter.Close();
% wait for the sort process to write the sorted text lines
process.WaitForExit();
process.Close();
end
For handling any output from the CMD you need:
function processOutputHandler(obj,event)
%collect the sort command output and print in command window
if(~isempty(event.Data))
disp(event.Data);
end
end
You can use a stream writer to synchronously write the sort input.
processStreamWriter = process.StandardInput;
Again, I have taken this from the previously mentioned post so I can't take any credit for the code, but I do think it will be able to accomplish what you are looking for. Unfortunately, I am pretty sure this will accomplish what you need. I don't have Matlab on a Windows platform at the moment or I would test this. If you need information on using .NET code in MATLAB (its not immediately clear if you need to add some stuff to establish the .NET interface) MathWorks provides some documentation on it: http://www.mathworks.com/help/matlab/matlab_external/using-net-from-matlab-an-overview.html
Hopefully this helps, or gets you started. Let me know if there's anything else I missed.
You can approach this from the ansys side. Start it with -B-R to read a python script.
From there, you can establish some two-way protocol, for example polling files or, better, by running a web server from python.
Then you can communicate from matlab with that running instance of ansys. If you opt for a web server, you use MATLABs urlread().
Setting up a web-server with python is easy, but you have to learn how to dispatch commands to the hosting ansys application.
I am trying to close a mutex that is being held by a process on Windows using Win32 functions. This can be done using procexp but I need to do it programmatically without using the procexp GUI.
Method1:
I tried injecting a dll into the processs using EasyHook and then tried the following from the injected thread:
- OpenMutex
- ReleaseMutex
It gave me the ERROR_NOT_OWNER error probably because the release was called on a different thread than the one that called AcquireMutex.
Method2:
After injecting the dll, I tried to hook for CreateMutex using mHook. The hooked CreateMutex just called back the original CreateMutex. But this would just crash the application.
I can use procexp to close the mutex but I need to do it programmatically. How does procexp do it? How can it be done programmatically without any kernel mode code?
Use NtQuerySystemInformation() to retrieve an array of open handles, loop through the array until you find the desired mutex handle in the target process, then close it using DuplicateHandle() by specifying the DUPLICATE_CLOSE_SOURCE flag.
The following article explains it in more detail:
HOWTO: Enumerate handles
Just adding a complete answer. I had to add the following the following code to handles.cpp after the mutex is recognized:
HANDLE realHandle;
ret = DuplicateHandle(processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &realHandle, 0, TRUE, DUPLICATE_CLOSE_SOURCE);
if(!ret)
printf("DuplicateHandle Problem!");
if (!CloseHandle(realHandle))
{
printf("Problem closing the copied handle");
}
printf("", realHandle);
}
When running a console application in Visual Studio, depending on your settings, it will add a prompt after the program exits:
Press any key to continue . . .
I have found how to detect if I am running under the debugger(use Debugger.IsAttached), but it isn't helpful. Press CTRL-F5 to Start Without Debugging sets this flag to false, yet still shows the prompt.
I want to detect this because I'd like to display my own message and wait for a keypress, but not double up keypress checks.
I don't want to muck with my general Visual Studio settings. If I can disable it for this project in a way that can be checked into source control, that would also work.
What mechanism is used to append this prompt, and how do I detect it?
Or how do I disable it per-project, and check this change into source control?
Add the following code to the console application:
public static class Extensions {
[DllImport("kernel32.dll")]
static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
[DllImport("kernel32.dll")]
static extern bool TerminateThread(IntPtr hThread, uint dwExitCode);
public static Process GetParentProcess(this Process x) {
return (
from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>()
where (uint)it["ProcessId"]==x.Id
select Process.GetProcessById((int)(uint)it["ParentProcessId"])
).First();
}
public static IEnumerable<Process> GetChildProcesses(this Process x) {
return (
from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>()
where (uint)it["ParentProcessId"]==x.Id
select Process.GetProcessById((int)(uint)it["ProcessId"])
);
}
public static void Abort(this ProcessThread x) {
TerminateThread(OpenThread(1, false, (uint)x.Id), 1);
}
}
And then modify your code like this:
class Program {
static void Main(String[] args) {
// ... (your code might goes here)
try {
Process.GetCurrentProcess().GetParentProcess().Threads.Cast<ProcessThread>().Single().Abort();
}
catch(InvalidOperationException) {
}
Console.Write("Press ONLY key to continue . . . ");
Console.ReadKey(true);
}
}
So, everything we are expecting is done now. I consider this as a workaround solution. It works under Windows XP SP3 and I guess that it would work with newer Windows operating systems. Under Visual Studio, applications are always a spawned process. In older Visual C++ 6.0, it spawned by the IDE by calling VCSPAWN.EXE; in Visual Studio 2010, your application runs with following command line when Start Without Debugging:
"%comspec%" /c ""your application filename" & pause"
So it is impossible to reach the goal in fully managed ways; because it was NOT under the application domain.
Here we use the managed way of WMI to enumerate the processes, and encapsulate the unmanaged WINAPIs to terminate the ProcessThreads, because the ProcessThread is not supposed to be normally aborted; it's provided like something for read-only.
As mentioned above, the application was spawned with the particular command line; it would have a single thread creates a single process signature, so we used the Single() method to retrieve that thread and terminate it.
When we start the application under an existing command prompt, it is just the same scenario of Start Without Debugging. Moreover, when Start Debugging, the application process is created by devenv.exe. It has a lot of threads, we known that and won't abort any thread, just prompt and wait for a key press. This situation is similar to starting application with double-clicking or from context menu. This way, the application process is created by the system shell, usually Explorer.exe and it also has a lots of threads.
In fact, if we can successfully abort the thread it implies that we have the permissions to kill the parent process. But we do NOT need to. We just need to abort the only thread, the process terminates automatically by system when it has no more threads. Killing the parent process by identifying that the calling process is %comspec%, is another way to do the same thing, but it's a dangerous procedure. Because the process spawning the application might have other threads which have any number of threads create a process matches %comspec%. You may kill a critical work of process with carelessness or just growing the complexity of checking whether the process is safe to kill. So I consider a single thread creates a single process as a signature of our parent process which is safe to kill/abort.
WMI is modern, some of WINAPIs might become deprecated in the future. But the real reason of this composition is for its simplicity. The old Tool Help Library is such complicated like the ways to convert ProcessThread to System.Threading.Thread. With LINQ and extension methods, we can make the code simpler and more semantical.
Sounds like this prompt is provided by the pause command. This command is automatically added by Visual Studio.
When you run your project outside of Visual Studio, there is no reason to "detect" this command. You can safely assume that it will not be added to your program. This means you can go ahead and add whatever prompt you want, similar to:
Console.WriteLine("Press any key...");
Console.Read();
See this question.
Here is a piece of code that should do it:
class Program
{
static void Main(string[] args)
{
// do your stuff
if (!WasStartedWithPause())
{
Console.WriteLine("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
public static bool WasStartedWithPause()
{
// Here, I reuse my answer at http://stackoverflow.com/questions/394816/how-to-get-parent-process-in-net-in-managed-way
Process parentProcess = ParentProcessUtilities.GetParentProcess();
// are we started by cmd.exe ?
if (string.Compare(parentProcess.MainModule.ModuleName, "cmd.exe", StringComparison.OrdinalIgnoreCase) != 0)
return false;
// get cmd.exe command line
string cmdLine = GetProcessCommandLine(parentProcess);
// was it started with a pause?
return cmdLine != null & cmdLine.EndsWith("& pause\"");
}
public static string GetProcessCommandLine(Process process)
{
if (process == null)
throw new ArgumentNullException("process");
// use WMI to query command line
ManagementObjectCollection moc = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId=" + process.Id).Get();
foreach (ManagementObject mo in moc)
{
return (string)mo.Properties["CommandLine"].Value;
}
return null;
}
That message has nothing to do with your program. You can add to your program anything you like and it will perform in the same way as it would, if you were to run it from the command prompt.
Visual studio displays it for the purpose of showing you that its execution has finished running, so you know it ended correctly. If you wish to skip it you could try to "run without debugging" (or something like that; it's just below "run with debugger").
This is the output of "pause" command which is added by visual studio. If you see this, the program is ended. Which comes to a question like is it possible for an application to detect that it self is ended. I think this is not logical.
Won't help to detect, but will add the same prompt when you run with debugger attached (F5) if you add this to the end of Main:
if (Debugger.IsAttached)
{
Console.Write("Press any key to continue . . . ");
Console.ReadKey();
}
It will in practice do the same as Ctrl + F5 does with & pause
This prompt is given when the command
system("pause")
is used.
Even I faced this problem. You can either use the function _getch() under conio.h for waiting for key press.
So you can use the following code:
cout<<"your message here"
_getch()
This would wait for the key press and display your own prompt.
Is it possible to somehow change standart I/O functions handle on Windows? Language preffered is C++. If I understand it right, by selecting console project, compiler just pre-allocate console for you, and operates all standart I/O functions to work with its handle. So, what I want to do is to let one Console app actually write into another app Console buffer. I though that I could get first´s Console handle, than pass it to second app by a file (I don´t know much about interprocess comunication, and this seems easy) and than somehow use for example prinf with the first app handle. Can this be done? I know how to get console handle, but I have no idea how to redirect printf to that handle. Its just study-purpose project to more understand of OS work behind this. I am interested in how printf knows what Console it is assiciated with.
If I understand you correctly, it sounds like you want the Windows API function AttachConsole(pid), which attaches the current process to the console owned by the process whose PID is pid.
If I understand you correct you can find the source code of application which you want to write in http://msdn.microsoft.com/en-us/library/ms682499%28VS.85%29.aspx. This example show how to write in stdin of another application and read it's stdout.
For general understanding. Compiler don't "pre-allocate console for you". Compiler use standard C/C++ libraries which write in the output. So if you use for example printf() the following code will be executed at the end will look like:
void Output (PCWSTR pszwText, UINT uTextLenght) // uTextLenght is Lenght in charakters
{
DWORD n;
UINT uCodePage = GetOEMCP(); // CP_OEMCP, CP_THREAD_ACP, CP_ACP
PSTR pszText = _alloca (uTextLenght);
// in the console are typically not used UNICODE, so
if (WideCharToMultiByte (uCodePage, 0, pszwText, uTextLenght,
pszText, uTextLenght, NULL, NULL) != (int)uTextLenght)
return;
WriteFile (GetStdHandle (STD_OUTPUT_HANDLE), pszText, uTextLenght, &n, NULL);
//_tprintf (TEXT("%.*ls"), uTextLenght, pszText);
//_puttchar();
//fwrite (pszText, sizeof(TCHAR), uTextLenght, stdout);
//_write (
}
So if one changes the value of STD_OUTPUT_HANDLE all output will be go to a file/pipe and so on. If instead of WriteFile the program use WriteConsole function such redirection will not works, but standard C/C++ library don't do this.
If you want redirect of stdout not from the child process but from the current process you can call SetStdHandle() directly (see http://msdn.microsoft.com/en-us/library/ms686244%28VS.85%29.aspx).
The "allocating of console" do a loader of operation system. It looks the word of binary EXE file (in the Subsystem part of IMAGE_OPTIONAL_HEADER see http://msdn.microsoft.com/en-us/library/ms680339%28VS.85%29.aspx) and if the EXE has 3 on this place (IMAGE_SUBSYSTEM_WINDOWS_CUI), than it use console of the parent process or create a new one. One can change a little this behavior in parameters of CreateProcess call (but only if you start child process in your code). This Subsystem flag of the EXE you define with respect of linker switch /subsystem (see http://msdn.microsoft.com/en-us/library/fcc1zstk%28VS.80%29.aspx).
If you want to redirect printf to a handle (FILE*), just do
fprintf(handle, "...");
For example replicating printf with fprintf
fprintf(stdout, "...");
Or error reporting
fprintf(stderr, "FATAL: %s fails", "smurf");
This is also how you write to files. fprintf(file, "Blah.");