Launch windows sound recorder app - c#

I want to start the default windows sound record in a Winforms app (c++/cli).In "Run" dialog, the command for Vista/7 is "soundrecorder". So I began with the easiest way:
System::Diagnostics::Process::Start("soundrecorder");
but it throws a System.ComponentModel.Win32Exception (Message: The System Cannot Find the File Specified). So I used the real path:
String^ path = Environment::GetFolderPath(Environment::SpecialFolder::System);
path = System::IO::Path::Combine(path, "soundrecorder.exe");
System::Diagnostics::Process::Start(path);
Same result. Hard-coding full path fail too. Any other command like "mspaint" runs correctly.
I thought that the problem was in my environment/current user/machine. Then I write a stupid program in C#:
public abstract class StupidProgram{
public static void Main(string[] args)
{
Process.Start("soundrecorder");
}
}
It works, and even more: If I run "StupidProgram.exe" from my app, it works too.
The application is coded in C++/CLI as 32-bits program. I'm working in Windows 7 64bits. I tested the app in a Windows 7 32bits and it works, so it seams a 32/64 bits compatibility issue.
Do you have any idea about this behaviour?

Quoting your C++/CLI code:
System::Diagnostics::Process::Start("soundrecord");
Quoting your C# code:
Process.Start("soundrecorder");
^^
Specifying "soundrecord" doesn't work, because it's called "soundrecord er"
Without the exact exception text, I think specifying the full path doesn't work because your application is being compiled as x86, and you're running 64-bit Windows, and the OS is doing filesystem redirection.
I recommend you use the equivalent to your C# command: Windows has the functionality to search the path for the executable, let it do so. Hard-coding the full path will give compatibility issues in the future, when MS decides to move it.
System::Diagnostics::Process::Start("soundrecorder");
^^

Related

Using Dotnet with NSIS fails on windows 7

I'm using an unmanaged C# dll (using DllExport and dotnet framework 4.0) to add UI capabilities to an NSIS installer, but basic controls constructors throw a font '?' cannot be found. exception on windows 7. Code example:
[DllExport]
public static void CreateRichTextBox()
{
try
{
RichTextBox myRichTextBox = new RichTextBox();
MessageBox.Show("RichTextBox created on windows 10");
}
catch (Exception ex)
{
MessageBox.Show("RichTextBox contractor failed on windows 7 with " + ex.Message);
}
}
So after some digging, I got to the conclusion that this happeneds because of a function used by NSIS that messes internal paths for the Dotnet: SetDefaultDllDirectories.
The function was added for security reasons explaind by the NSIS team:
Using SetDefaultDllDirectories we can globally change the behavior
of LoadLibraryEx so that it only looks into the System32 folder and into any
directories explicitly added with AddDllDirectories.
I only guess that this is a Gdiplus bug that was eventually solved but I still wonder if someone knows of a workaround to make it work on windows 7?
The public Microsoft bug report claims the bug is in Windows (GDI+) and not technically a .NET specific issue.
Unfortunately MSDN says this about SetDefaultDllDirectories:
It is not possible to revert to the standard DLL search path or remove any directory specified with SetDefaultDllDirectories from the search path. ...
This means the only workaround is to not call the function in the first place. The only way to do that in NSIS is to use a hex-editor and modify the stubs in NSIS\Stubs. Search for SetDefaultDllDirectories in the relevant stub and change it to something like SetDefaultxxxxxxxxxxxxxx (replace as many characters as you want but the length has to stay the same!).
This of course means that your installer will be somewhat vulnerable to malicious .DLL planting attacks. You can try to restore the functionality somewhat with:
!include WinVer.nsh
!include LogicLib.nsh
Function .onInit
${If} ${AtLeastWin8}
System::Call 'KERNEL32::SetDefaultDllDirectories(i 0x800|0x400)'
${EndIf}
FunctionEnd
but the protection is slightly less effective this way and does nothing on Windows 7.

Mono cannot access file even though linux shell can without root

this might be a wrong place to ask this (but I think its right place since it involves programming).
So I got a raspberry pi zero for our school project. I SSH'd into it to check out what it can do with it. I made some research about how to use the GPIO pins on this card.
Basically:
$ echo 17 > /sys/class/gpio/export
$ echo out > /sys/class/gpio/gpio17/direction
$ echo 1 > /sys/class/gpio/gpio17/value
$ echo 17 > /sys/class/gpio/unexport
Enables GPIO pin 17 and writes digital 1 into it and 'unexport's it, no root is needed.
I also wanted to try out some of the languages in this card. I tried python, C# and Rust without a problem (even though rust compiles very slow, it works). So I started using my favourite language C# with mono. Installing it and compiling a basic program wasn't a big deal, It works.
So I write this:
using System;
using System.IO;
namespace Program
{
public static class Program
{
public static void Main()
{
if (Directory.Exists("/sys/class/gpio/gpio17/"))
File.WriteAllText("/sys/class/gpio/unexport", "17");
File.WriteAllText("/sys/class/gpio/export", "17");
File.WriteAllText("/sys/class/gpio/gpio17/direction", "out");
File.WriteAllText("/sys/class/gpio/gpio17/value", "1");
}
}
}
Basically, if it finds the 17 pin open, 'unexport' it then re-export it, set as output and write digital 1.
Compilation:
mcs program.cs -out:program.exe -debug && ./program.exe
Output:
Unhandled Exception:
System.UnauthorizedAccessException: Access to the path "/sys/class/gpio/gpio17/direction" is
denied.
What? How? It works with sudo mono ./program.exe and no it doesn't with mono ./program.exe
Sure, I can always use wiringPi or python but I am curious about this one and couldn't find an answer. It doesn't make sense to me. /sys/class/gpio/gpio17 is a symbolic link and I tried to access to original path too with no luck.
What might be the problem here?
Guesses:
You unexport it first, then export it and immediately access it, I had in the past several time problems on some OS e. g. deleting a file and immediately creating it again, add a waiting time (not really clean code, but if it works)
check the difference of the files/folders with linux command "ls -la" or more
call the shell command, that worked, from C# via e. g. Process class
Some few times Mono did not work like C# on Windows, a workaround had to be found
try to open a stream to these files and leave them open? Or even a pipe is possible to these files?

Universal Windows Platform (UWP) C# app - How to run stand alone python inside your application

I am trying to find a way to call python from my UWP app. So far I have a .exe file that I have compiled from python using pyinstaller (www.pyinstaller.org/). This basically allows me to package up my python script as a standalone binary (ie: you don't need python to run it). This all works well and I can call my wrapped up python .exe via cmd.exe no problem:
$ process.exe -p "path\to\file"
$ Processing file: "path\to\file"...
$ Done.
So now I just need to call it from my UWP app - so I have added it to my application like so:
C# Project
Assets/process.exe
Frustratingly, I've not had much luck googling for answers to my problem - my attempted solutions so far have included:
Calling the "Assets/process.exe" directly from my app
Looked at "Launch an app and get results". I think this seams to be for external applications however... I certainly didn't get it going anyway.
Opening the cmd.exe (somehow) and calling my process.exe from there.
I'm not even sure if I'm trying to do this the correct way or not. Or if I have just not understood some of my findings. Or (fingers crossed) there is a simple solution to this I just don't know about and have somehow missed as I'm very new to UWP development and C#.
So any solutions/pointers here would be greatly appreciated thanks!!
UWP apps are 'sandboxed'; i.e. they have many security restrictions placed upon them to isolate them from the rest of Windows (like not being able to read/write to the Registry and not being able to directly access random files from the file system).
So there is no way to run an .exe (or any other executable) from your UWP app. If you have access to a StorageFile (say music, video or any other file format) then you can launch the file in the default program associated with that file type.

Programmatically start a process independent of platform

Situation
I am trying to run a command-line tool, DISM.exe, programmatically. When I run it manually it works, but when I try to spawn it with the following:
var systemPath = Environment.GetFolderPath(Environment.SpecialFolder.System);
var dism = new Process();
dism.StartInfo.FileName = Path.Combine(systemPath, "Dism.exe");
dism.StartInfo.Arguments = "/Online /Get-Features /Format:Table";
dism.StartInfo.Verb = "runas";
dism.StartInfo.UseShellExecute = false;
dism.StartInfo.RedirectStandardOutput = true;
dism.Start();
var result = dism.StandardOutput.ReadToEnd();
dism.WaitForExit();
Then my result comes out as:
Error: 11
You cannot service a running 64-bit operating system with a 32-bit version of DISM.
Please use the version of DISM that corresponds to your computer's architecture.
Problem
I'm actually already aware of what causes this: my project is set up to compile for an x86 platform. (See this question for example, although none of the answers mention this). However, unfortunately it is a requirement at the moment that we continue targeting this platform, I am not able to fix this by switching to Any CPU.
So my question is how to programmatically spawn a process in a way which is independent of the platform of its parent- i.e. keep my project targeting x86, but start a process which will target the correct platform for the machine it is on.
even though I'm running the correct DSIM.exe in System32
But you're not. That's the point. The file system redirector lies to 32-bit processes and so when you ask for System32 from an x86 process, you actually get the file from SysWow64. If you want to access the 64-bit exe, you need to ask for it via %windir%\sysnative
(%windir% being SpecialFolder.Windows)
While it's not answering your question about starting a 64 bit process from a 32 bit, an alternative approach to your underlying problem would be to query WMI to obtain the information you require. You can list optional features or list Server Features
This answer gives general information about performing a WMI query from C#.
You can also check and install windows features from powershell, which you might be able to spawn from your program instead of starting DISM.

Any kind of way of detecting case-sensitve filename errors?

we are making a project to run in ASP.Net on Mono/*nix
Our problem is that we develop on Windows, and we just build and test it every so often on Mono. So we have been having a lot of trouble recently with case sensitive filenames. Everything seems to work good in Windows and then we move to Mono and it's silently broken.(as in, it builds but won't run or parts of it don't work)
How would you recommend that I detect this while we are developing on Windows? Basically, how do we make the case-sensitive filenames look wrong in our code where the code works on Windows but not *nix?
One thing you can do is use MONO_IOMAP so that Mono silently corrects the errors and emulates a case-insensitive file system:
http://www.mono-project.com/IOMap
Another thing you can use to actually find the issues is a new "profiler module" that logs every time a string triggers MONO_IOMAP and tells you where in your code it was created:
http://twistedcode.net/blog/post/2009/12/21/A-utility-to-help-porting-Windows-NET-applications-to-MonoUnix.aspx
You could use a compiler directive which would indicate when you are building for *nix systems which would validate the file paths.

Categories