How to install a windows font using C# - c#

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);
}

Related

How to open file with Process.Start if there is no associated program for the file type?

When I want to open an .ico file using Process.Start it throws an error System.ComponentModel.Win32Exception and this is because there is no default program to open that file. I need to show the window to select the default program instead of throwing exception. How can I do that?
private void btnOpenFile_Click(object sender, EventArgs e)
{
Process.Start(txtSavedAs.Text);
}
What you want to do is pinvoke the AssocQueryString API. Documentation here.
I use that API to get a command string associated with a shell verb. So, for example, if I use the .txt extension, it would return:
C:\Windows\system32\NOTEPAD.EXE %1
Now we know that shell knows what program to execute and how to pass in the command-line argument for that specific extension.
So, if there is a "Command" associated with that extension, it is safe to assume shell will know how to execute that type of file; Hence we should be able to use ShellExecute normally.
If there is no "Command" associated with that file extension, we will show the "openas" dialog allowing the user to pick the application they want to open the file.
Here is a class I put together to do that work:
AppAssociation.cs
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
public static class AppAssociation
{
private static class Win32Native
{
public const int ASSOCF_NONE = 0;
public const int ASSOCSTR_COMMAND = 1;
[DllImport("shlwapi.dll", CharSet = CharSet.Unicode,
EntryPoint = "AssocQueryStringW")]
public static extern uint AssocQueryString(int flags, int str,
string pszAssoc, string pszExtra, StringBuilder pszOut, ref uint pcchOut);
}
public static Process StartProcessForFile(FileInfo file)
{
var command = GetCommandForFileExtention(file.Extension);
return Process.Start(new ProcessStartInfo()
{
WindowStyle = ProcessWindowStyle.Normal,
FileName = file.FullName,
Verb = string.IsNullOrEmpty(command) ? "openas" : null,
UseShellExecute = true,
ErrorDialog = true
});
}
private static string GetCommandForFileExtention(string ext)
{
// query length of the buffer we need
uint length = 0;
if (Win32Native.AssocQueryString(Win32Native.ASSOCF_NONE,
Win32Native.ASSOCSTR_COMMAND, ext, null, null, ref length) == 1)
{
// build the buffer
var sb = new StringBuilder((int)length);
// ask for the actual command string with the right-sized buffer
if (Win32Native.AssocQueryString(Win32Native.ASSOCF_NONE,
Win32Native.ASSOCSTR_COMMAND, ext, null, sb, ref length) == 0)
{
return sb.ToString();
}
}
return null;
}
}
You would call this like so:
AppAssociation.StartProcessForFile(new FileInfo(#"c:\MyFiles\TheFile.txt"));

Dot net core C# open photo viewer with Process Class

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");
}

Find out the letter of the USB [duplicate]

How do I find the application's path in a console application?
In Windows Forms, I can use Application.StartupPath to find the current path, but this doesn't seem to be available in a console application.
System.Reflection.Assembly.GetExecutingAssembly().Location1
Combine that with System.IO.Path.GetDirectoryName if all you want is the directory.
1As per Mr.Mindor's comment:
System.Reflection.Assembly.GetExecutingAssembly().Location returns where the executing assembly is currently located, which may or may not be where the assembly is located when not executing. In the case of shadow copying assemblies, you will get a path in a temp directory. System.Reflection.Assembly.GetExecutingAssembly().CodeBase will return the 'permanent' path of the assembly.
You can use the following code to get the current application directory.
AppDomain.CurrentDomain.BaseDirectory
You have two options for finding the directory of the application, which you choose will depend on your purpose.
// to get the location the assembly is executing from
//(not necessarily where the it normally resides on disk)
// in the case of the using shadow copies, for instance in NUnit tests,
// this will be in a temp directory.
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
//To get the location the assembly normally resides on disk or the install directory
string path = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
//once you have the path you get the directory with:
var directory = System.IO.Path.GetDirectoryName(path);
Probably a bit late but this is worth a mention:
Environment.GetCommandLineArgs()[0];
Or more correctly to get just the directory path:
System.IO.Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]);
Edit:
Quite a few people have pointed out that GetCommandLineArgs is not guaranteed to return the program name. See The first word on the command line is the program name only by convention. The article does state that "Although extremely few Windows programs use this quirk (I am not aware of any myself)". So it is possible to 'spoof' GetCommandLineArgs, but we are talking about a console application. Console apps are usually quick and dirty. So this fits in with my KISS philosophy.
Edit
It seems, from feedback, that most of the other solutions don't work when you are using a unit testing system. This sort of makes sense as the executable item is not your application but the testing system. I have not checked this out - so I could be completely wrong. If this is so, I will delete this edit.
For anyone interested in asp.net web apps. Here are my results of 3 different methods
protected void Application_Start(object sender, EventArgs e)
{
string p1 = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string p2 = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath;
string p3 = this.Server.MapPath("");
Console.WriteLine("p1 = " + p1);
Console.WriteLine("p2 = " + p2);
Console.WriteLine("p3 = " + p3);
}
result
p1 = C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\a897dd66\ec73ff95\assembly\dl3\ff65202d\29daade3_5e84cc01
p2 = C:\inetpub\SBSPortal_staging\
p3 = C:\inetpub\SBSPortal_staging
the app is physically running from "C:\inetpub\SBSPortal_staging", so the first solution is definitely not appropriate for web apps.
The answer above was 90% of what I needed, but returned a Uri instead of a regular path for me.
As explained in the MSDN forums post, How to convert URI path to normal filepath?, I used the following:
// Get normal filepath of this assembly's permanent directory
var path = new Uri(
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().CodeBase)
).LocalPath;
If you are looking for a .NET Core compatible way, use
System.AppContext.BaseDirectory
This was introduced in .NET Framework 4.6 and .NET Core 1.0 (and .NET Standard 1.3). See: AppContext.BaseDirectory Property.
According to this page,
This is the prefered replacement for AppDomain.CurrentDomain.BaseDirectory in .NET Core
You may be looking to do this:
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
you can use this one instead.
System.Environment.CurrentDirectory
For Console Applications, you can try this:
System.IO.Directory.GetCurrentDirectory();
Output (on my local machine):
c:\users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug
Or you can try (there's an additional backslash in the end):
AppDomain.CurrentDomain.BaseDirectory
Output:
c:\users\xxxxxxx\documents\visual studio 2012\Projects\ImageHandler\GetDir\bin\Debug\
I have used this code and get the solution.
AppDomain.CurrentDomain.BaseDirectory
Following line will give you an application path:
var applicationPath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName)
Above solution is working properly in the following situations:
simple app
in another domain where Assembly.GetEntryAssembly() would return null
DLL is loaded from Embedded resources as a byte array and loaded to AppDomain as Assembly.Load(byteArrayOfEmbeddedDll)
with Mono's mkbundle bundles (no other methods work)
You can simply add to your project references System.Windows.Forms and then use the System.Windows.Forms.Application.StartupPath as usual .
So, not need for more complicated methods or using the reflection.
I have used
System.AppDomain.CurrentDomain.BaseDirectory
when I want to find a path relative to an applications folder. This works for both ASP.Net and winform applications. It also does not require any reference to System.Web assemblies.
I mean, why not a p/invoke method?
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
public class AppInfo
{
[DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = false)]
private static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
private static HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
public static string StartupPath
{
get
{
StringBuilder stringBuilder = new StringBuilder(260);
GetModuleFileName(NullHandleRef, stringBuilder, stringBuilder.Capacity);
return Path.GetDirectoryName(stringBuilder.ToString());
}
}
}
You would use it just like the Application.StartupPath:
Console.WriteLine("The path to this executable is: " + AppInfo.StartupPath + "\\" + System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe");
Assembly.GetEntryAssembly().Location or Assembly.GetExecutingAssembly().Location
Use in combination with System.IO.Path.GetDirectoryName() to get only the directory.
The paths from GetEntryAssembly() and GetExecutingAssembly() can be different, even though for most cases the directory will be the same.
With GetEntryAssembly() you have to be aware that this can return null if the entry module is unmanaged (ie C++ or VB6 executable). In those cases it is possible to use GetModuleFileName from the Win32 API:
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern int GetModuleFileName(HandleRef hModule, StringBuilder buffer, int length);
I use this if the exe is supposed to be called by double clicking it
var thisPath = System.IO.Directory.GetCurrentDirectory();
in VB.net
My.Application.Info.DirectoryPath
works for me (Application Type: Class Library). Not sure about C#...
Returns the path w/o Filename as string
I didn't see anyone convert the LocalPath provided by .Net Core reflection into a usable System.IO path so here's my version.
public static string GetApplicationRoot()
{
var exePath = new Uri(System.Reflection.
Assembly.GetExecutingAssembly().CodeBase).LocalPath;
return new FileInfo(exePath).DirectoryName;
}
This will return the full C:\\xxx\\xxx formatted path to where your code is.
AppDomain.CurrentDomain.BaseDirectory
Will resolve the issue to refer the 3rd party reference files with installation packages.
With .NET Core 3 and above you will get the .dll and not the .exe file. To get the .exe file path you can use.
var appExePath = Process.GetCurrentProcess().MainModule.FileName;
Try this simple line of code:
string exePath = Path.GetDirectoryName( Application.ExecutablePath);
For .NET 6 there's Environment.ProcessPath.
See https://learn.microsoft.com/en-us/dotnet/api/system.environment.processpath?view=net-6.0
None of these methods work in special cases like using a symbolic link to the exe, they will return the location of the link not the actual exe.
So can use QueryFullProcessImageName to get around that:
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;
internal static class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool QueryFullProcessImageName([In]IntPtr hProcess, [In]int dwFlags, [Out]StringBuilder lpExeName, ref int lpdwSize);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr OpenProcess(
UInt32 dwDesiredAccess,
[MarshalAs(UnmanagedType.Bool)]
Boolean bInheritHandle,
Int32 dwProcessId
);
}
public static class utils
{
private const UInt32 PROCESS_QUERY_INFORMATION = 0x400;
private const UInt32 PROCESS_VM_READ = 0x010;
public static string getfolder()
{
Int32 pid = Process.GetCurrentProcess().Id;
int capacity = 2000;
StringBuilder sb = new StringBuilder(capacity);
IntPtr proc;
if ((proc = NativeMethods.OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, pid)) == IntPtr.Zero)
return "";
NativeMethods.QueryFullProcessImageName(proc, 0, sb, ref capacity);
string fullPath = sb.ToString(0, capacity);
return Path.GetDirectoryName(fullPath) + #"\";
}
}
Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName)
Is the only one that has worked for me in every case I have tried.
In .NET 6, my WPF app (<TargetFramework>net6.0-windows</TargetFramework>) returns the .dll file path for Assembly.GetEntryAssembly()!.Location instead of the .exe file. They introduced System.Environment.ProcessPath for this purpose:
var path = Environment.ProcessPath; // Note it may be null
Returns the path of the executable that started the currently executing process. Returns null when the path is not available.
See discussion for it here and here.
I use this for console + net 6
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
The techniques, and pitfalls, keep changing. The below assumes you're running a .NET 6 console app on linux (on win/mac the results will follow a similar pattern, just replace /usr/share/ and /home/username/ with the standard locations for your OS).
Demo:
Console.WriteLine("Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName) = " + Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName));
Console.WriteLine("Path.GetDirectoryName(Environment.ProcessPath) = " + Path.GetDirectoryName(Environment.ProcessPath));
Console.WriteLine("Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) = " + Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
Console.WriteLine("typeof(SomeType).Assembly.Location = " + typeof(SomeType).Assembly.Location);
Console.WriteLine("Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) = " + Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]));
Console.WriteLine("AppDomain.CurrentDomain.BaseDirectory = " + AppDomain.CurrentDomain.BaseDirectory);
Console.WriteLine("System.AppContext.BaseDirectory = " + System.AppContext.BaseDirectory);
Results:
Path.GetDirectoryName(Process.GetCurrentProcess()?.MainModule?.FileName) = /usr/share/dotnet
Path.GetDirectoryName(Environment.ProcessPath) = /usr/share/dotnet
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) = /home/username/myproject/bin/Debug/net6.0
typeof(SomeType).Assembly.Location = /home/username/myproject/bin/Debug/net6.0
Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) = /home/username/myproject/bin/Debug/net6.0
AppDomain.CurrentDomain.BaseDirectory = /home/username/myproject/bin/Debug/net6.0/
System.AppContext.BaseDirectory = /home/username/myproject/bin/Debug/net6.0/
Each approach has its own pros and cons - see the other answers to learn in which uses cases to use which approach.
I run my .NET 6 console app with dotnet myapp, so what works (reliably) for me is either of:
typeof(SomeType).Assembly.Location
// or
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Here is a reliable solution that works with 32bit and 64bit applications.
Add these references:
using System.Diagnostics;
using System.Management;
Add this method to your project:
public static string GetProcessPath(int processId)
{
string MethodResult = "";
try
{
string Query = "SELECT ExecutablePath FROM Win32_Process WHERE ProcessId = " + processId;
using (ManagementObjectSearcher mos = new ManagementObjectSearcher(Query))
{
using (ManagementObjectCollection moc = mos.Get())
{
string ExecutablePath = (from mo in moc.Cast<ManagementObject>() select mo["ExecutablePath"]).First().ToString();
MethodResult = ExecutablePath;
}
}
}
catch //(Exception ex)
{
//ex.HandleException();
}
return MethodResult;
}
Now use it like so:
int RootProcessId = Process.GetCurrentProcess().Id;
GetProcessPath(RootProcessId);
Notice that if you know the id of the process, then this method will return the corresponding ExecutePath.
Extra, for those interested:
Process.GetProcesses()
...will give you an array of all the currently running processes, and...
Process.GetCurrentProcess()
...will give you the current process, along with their information e.g. Id, etc. and also limited control e.g. Kill, etc.*
You can create a folder name as Resources within the project using Solution Explorer,then you can paste a file within the Resources.
private void Form1_Load(object sender, EventArgs e) {
string appName = Environment.CurrentDirectory;
int l = appName.Length;
int h = appName.LastIndexOf("bin");
string ll = appName.Remove(h);
string g = ll + "Resources\\sample.txt";
System.Diagnostics.Process.Start(g);
}

How to debug LoadLibraryEx when used from C#

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.

how to start console screen in windows service

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.

Categories