i use Tow methods to log my application (windows app) to file and console screen
public static void InitLogFile(string filename)
{
FileStream fs = new FileStream(filename, FileMode.Create);
Trace.Listeners.Add(new TextWriterTraceListener(fs));
Trace.AutoFlush = true;
}
public static void InitConsole()
{
Trace.Listeners.Add(new ConsoleTraceListener());
Trace.AutoFlush = true;
}
and i use this code for start the console screen when my windows application is started
[DllImport("kernel32.dll",EntryPoint = "GetStdHandle",SetLastError = true,CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll",EntryPoint = "AllocConsole",SetLastError = true,CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int AllocConsole();
private const int STD_OUTPUT_HANDLE = -11;
private const int MY_CODE_PAGE = 437;
void StartConsole()
{
AllocConsole();
IntPtr stdHandle = GetStdHandle(STD_OUTPUT_HANDLE);
var safeFileHandle = new SafeFileHandle(stdHandle, true);
var fileStream = new FileStream(safeFileHandle, FileAccess.Write);
var encoding = Encoding.GetEncoding(MY_CODE_PAGE);
var standardOutput = new StreamWriter(fileStream, encoding) {AutoFlush = true};
Console.SetOut(standardOutput);
}
My Question is :
I convert my windows Application to windows service the console log screen is not working not appearing now how make it work?
A Windows Service does not run like a standard Windows application. It could be running when no users are logged on to the computer so how could a console screen appear?
When running as a service you should consider writing to the Windows Event Log or some other logging mechanism instead.
The reason you don't see anything is because of Session 0 Isolation.
However, there is a nice codeproject article which will run an app from a service, in the user session.
Just put your code into a exe file, and launch the exe file using the project in the link.
Related
I am going to open the photo viewer using .net core and this is my code
using System.Diagnostics;
namespace TestProcessForOpenPhoto
{
class Program
{
static void Main(string[] args)
{
var photoViewer = new Process();
photoViewer.StartInfo.FileName = #"C:\Program Files\Windows Photo Viewer\PhotoViewer.dll";
photoViewer.StartInfo.Arguments = #" C:\Users\XXXXX\Desktop\TestImage\abc.jpg";
photoViewer.StartInfo.UseShellExecute = false;
photoViewer.Start();
}
}
}
and I got this error message
System.ComponentModel.Win32Exception: 'The specified executable is not a valid application for this OS platform.'
Can anyone help me to fix this bug, thanks
After researching this I noticed folks using rundll32.exe to execute an export from PhotoViewer.dll to display a picture using Microsoft Photo Viewer application. So I think that's what OP was trying to do, they just forgot to use the rundll32.exe application.
So I thought I'd take a crack at this and not use the rundll32.exe and just call the export directly. I debugged it with x86dbg and saw that it's passing in 4 parameters: pointer, pointer, pointer (to wchar_t*), int. I don't know what the parameters do, so I just set them to NULL and made sure to pass in the path to the picture as the 3rd and it seems to work.
So this will do what you want it to do. I know that hard-coding system paths is bad practice, but maybe someone who has more time can make this more dynamic.
private static class WindowsPhotoViewer
{
private const string FilePath32 = #"c:\program files (x86)\Windows Photo Viewer\PhotoViewer.dll";
private const string FilePath64 = #"c:\program files\Windows Photo Viewer\PhotoViewer.dll";
[DllImport(FilePath32, CharSet = CharSet.Unicode, EntryPoint = "ImageView_FullscreenW")]
private static extern void ImageView_Fullscreen32(
IntPtr unknown1, IntPtr unknown2, string path, int unknown3);
[DllImport(FilePath64, CharSet = CharSet.Unicode, EntryPoint = "ImageView_FullscreenW")]
private static extern void ImageView_Fullscreen64(
IntPtr unknown1, IntPtr unknown2, string path, int unknown3);
public static bool ShowImage(FileInfo imageFile)
{
if ((IntPtr.Size == 8) && File.Exists(FilePath64) && imageFile.Exists)
{
ImageView_Fullscreen64(IntPtr.Zero, IntPtr.Zero, imageFile.FullName, 0);
return true;
}
else if ((IntPtr.Size == 4) && File.Exists(FilePath32) && imageFile.Exists)
{
ImageView_Fullscreen32(IntPtr.Zero, IntPtr.Zero, imageFile.FullName, 0);
return true;
}
return false;
}
}
Then you can call it as so:
if(!WindowsPhotoViewer.ShowImage(new FileInfo(#"c:\users\andy\desktop\test.jpg")))
{
Console.WriteLine("Failed to show image");
}
I have the following problem. I want to open an embedded textfile (agb.txt) using "notepad.exe". I've got the following code:
private void linkLabel4_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
string editorPath = Environment.SystemDirectory + "\\notepad.exe";
var startInfo = new ProcessStartInfo(editorPath)
{
//Start Maximized
WindowStyle = ProcessWindowStyle.Maximized,
Arguments = "agb.txt"
};
//Start notepad.exe (agb.txt)
Process.Start(startInfo);
}
When I start the program and click the Linklabel, Notpad.exe open up but can't find the embedded file (obviously). So is there a kinda 'Workaround'?
What about saving the file to %TEMP% and then simply calling
Process.Start(#"c:\temp\agb.txt");
(this will actually open the file in whatever application is registered to load it)
You can start Nodepad.exe and then "send" the text from the embedded file to it.
Instead of my hardcoded string, you would read the content of the file into a string and then call DoSendMessage(stringWithYourFileContent);
This question and answer is a good resource for reading the content of the embedded file: How to read embedded resource text file
class Program
{
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
static void Main(string[] args)
{
DoSendMessage("Sending a message, a message from me to you");
}
private static void DoSendMessage(string message)
{
Process notepad = Process.Start(new ProcessStartInfo("notepad.exe"));
notepad.WaitForInputIdle();
if (notepad != null)
{
IntPtr child = FindWindowEx(notepad.MainWindowHandle, new IntPtr(0), "Edit", null);
SendMessage(child, 0x000C, 0, message);
}
}
}
The constant 0x000c of SendMessage is documented here
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632644(v=vs.85).aspx
. The constant says SETTEXT which really means that the text in
notepad will be replaced if you send more than one message using this
constant.
I am trying to load a win32 dll in C# using the LoadLibraryEx.
It is not working - I get a message stating in visual studio "vshost32.exe has stopped working". No exceptions or any clue as to why it doesn't work.
I don't believe it is a dependency problem because if I alter the search paths for the dependencies I get a message box stating "xyz.dll could not be found".
I am wondering if there is a way I can find out why it doesn't load properly. The program stops working on the line:
IntPtr pDll = LoadLibraryEx(#"C:\Program Files\XXX\XXX.dll", IntPtr.Zero, flags);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ImportResults();
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr hFile, LoadLibraryFlags flags);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FreeLibrary(IntPtr hModule);
[System.Flags]
public enum LoadLibraryFlags : uint
{
DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100,
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000
}
public void Import()
{
LoadLibraryFlags flags = LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
IntPtr pDll = LoadLibraryEx(#"C:\Program Files\XXX\XXX.dll", IntPtr.Zero, flags);
IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "ImportResults");
ImportResults import = (ImportResults)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,
typeof(ImportResults));
import();
bool result = FreeLibrary(pDll);
}
Update:
I have downloaded the windows sdk and am attempting to use the cdb.exe to debug the problem using the process described here: http://blogs.msdn.com/b/junfeng/archive/2006/11/20/debugging-loadlibrary-failures.aspx
When running the utility I am using this command line:
"C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\cdb.exe" loadlib "C:\Program Files\XXX\XXX\XXX.DLL"
But I get this error:
The file definitely exists so I am unsure what I am doing wrong here.
I installed the windows debugging tools: https://msdn.microsoft.com/en-US/windows/desktop/bg162891
I then downloaded the Windows Symbol packages: https://msdn.microsoft.com/en-us/windows/hardware/gg463028.aspx
Then set an environment variable to tell the debugger where to look for symbols:
_NT_SYMBOL_PATH = SRV*C:\dev\symbols*http://msdl.microsoft.com/download/symbols;C:\Symbols
(I installed the symbol package to C:\Symbols)
Then I started my application and attached the debugger with this command:
"C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\cdb.exe" -pb -p <pid>
-pb means it won't break on exceptions
-p is the pid of the thread you want to debug
From this I have been able to determine where the error is happening. Still haven't figured out why it's happening though.
I want to association ".abc" file to my WPF application.
I add the association using this code:
public class FileAssociation
{
static RegistryKey Root
{
get
{
return Registry.CurrentUser;
}
}
// Associate file extension with progID, description, icon and application
public static void Associate(string extension,
string progID, string description, string application)
{
Require.NotNullOrEmpty(extension, "extension");
Require.NotNullOrEmpty(progID, "progID");
Require.NotNullOrEmpty(application, "application");
Require.NotNullOrEmpty(description, "description");
Root.CreateSubKey(extension).SetValue("", progID);
using (var key = Root.CreateSubKey(progID))
{
key.SetValue("", description);
key.CreateSubKey("DefaultIcon").SetValue("", ToShortPathName(application).Quote() + ",0");
key.CreateSubKey(#"Shell\Open\Command").SetValue("", ToShortPathName(application).Quote() + " \"%1\"");
// Tell explorer the file association has been changed
SHChangeNotify(0x08000000, 0x0000, IntPtr.Zero, IntPtr.Zero);
}
}
// Return true if extension already associated in registry
public static bool IsAssociated(string extension)
{
return (Root.OpenSubKey(extension, false) != null);
}
[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
[DllImport("Kernel32.dll")]
private static extern uint GetShortPathName(string lpszLongPath,
[Out] StringBuilder lpszShortPath, uint cchBuffer);
// Return short path format of a file name
private static string ToShortPathName(string longName)
{
StringBuilder s = new StringBuilder(1000);
uint iSize = (uint)s.Capacity;
uint iRet = GetShortPathName(longName, s, iSize);
return s.ToString();
}
}
Note: The Quote() extension method is used just to make string abc to "abc".
Now the file association works fine! I can double click the ".abc" files to open my WPF app.
But the DefaultIcon is not working. The DefaultIcon Registery key is set to "D:\path\to\MyWPFApp.exe",0. The application icon of my WPF app is set to an icon in the properties page (I can see that the icon of MyWPFApp.exe is already changed). What's wrong? Thanks!
BTW: I'm using .NET 4 in Windows 8
You don't need the DefaultIcon entry. The first icon is used by default.
remove it and it should work ^^
If I remove the ToShortPathName (long name is ok with quotes) and
change the Root property returns Registry.ClassesRoot the code works here.
How can I install a font using C#?
I tried copying the fonts using File.Copy() but I am not allowed due to access rights limitations (UnauthorizedException).
What should I do?
You'll need a different approach installing fonts.
Use an installer (create a setup project) to install the fonts
Another (more easy) approach using a native method.
Declare the dll import:
[DllImport("gdi32.dll", EntryPoint="AddFontResourceW", SetLastError=true)]
public static extern int AddFontResource(
[In][MarshalAs(UnmanagedType.LPWStr)]
string lpFileName);
In your code:
// Try install the font.
result = AddFontResource(#"C:\MY_FONT_LOCATION\MY_NEW_FONT.TTF");
error = Marshal.GetLastWin32Error();
The source:
http://www.brutaldev.com/post/2009/03/26/Installing-and-removing-fonts-using-C
I put it together in a unit test, I hope that helps:
[TestFixture]
public class Tests
{
// Declaring a dll import is nothing more than copy/pasting the next method declaration in your code.
// You can call the method from your own code, that way you can call native
// methods, in this case, install a font into windows.
[DllImport("gdi32.dll", EntryPoint = "AddFontResourceW", SetLastError = true)]
public static extern int AddFontResource([In][MarshalAs(UnmanagedType.LPWStr)]
string lpFileName);
// This is a unit test sample, which just executes the native method and shows
// you how to handle the result and get a potential error.
[Test]
public void InstallFont()
{
// Try install the font.
var result = AddFontResource(#"C:\MY_FONT_LOCATION\MY_NEW_FONT.TTF");
var error = Marshal.GetLastWin32Error();
if (error != 0)
{
Console.WriteLine(new Win32Exception(error).Message);
}
}
}
That should help you on your way :)
internal static void InstalarFuente(string NombreFnt,string RutaFnt)
{
string CMD = string.Format("copy /Y \"{0}\" \"%WINDIR%\\Fonts\" ", RutaFnt);
EjecutarCMD(CMD);
System.IO.FileInfo FInfo = new System.IO.FileInfo(RutaFnt);
CMD = string.Format("reg add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts\" /v \"{0}\" /t REG_SZ /d {1} /f", NombreFnt, FInfo.Name);
EjecutarCMD(CMD);
}
public static void EjecutarCMD(string Comando)
{
System.Diagnostics.ProcessStartInfo Info = new System.Diagnostics.ProcessStartInfo("cmd.exe");
Info.Arguments = string.Format("/c {0}", Comando);
Info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
System.Diagnostics.Process.Start(Info);
}