I use VS2005 on Windows Vista.
I create a very simple Windows application in C# using .NET 2.0, a form with a close button.
Due to a necessary library, I need the VS-option target platform "x86". If I build on Vista and transfer the application to a X64 Windows 7 computer, the application requires administrator rights for execution (UAC-Message-Dialog), which I want to avoid.
If using the VS-option target platform "anyCPU", this works fine, but I need a solution for the target platform "x86".
Can anybody help me?
What I want to do is to change the code or the project configuration to avoid the UAC-Message-Dlg on Windows7 (x64). But I don’t know what I have to do. I need the option “x86”, because we want to use an x86 library. The test code is totally simple (see below), so I presume the problem is in the project configuration:
// Project code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Updater2
{
public partial class Form1 : Form
{
public Form1( )
{
InitializeComponent( );
}
private void toolStripButton1_Click( object sender, EventArgs e )
{
Close( );
} // -- toolStripButtonClose_Click
} // - Form1
}
Chances are you are trying to write files to the C:/ or C:/Program Files folder. Try writing any files to the %Current User% folder to avoid UAC. Apart from that, without seeing any of your code, I can't offer much more of a solution.
The problem is the word "Update" in the program name.
When an executable has words like "Update", "Install" or "Setup" in its name, Windows assumes it may be an installer which will most likely require administrative rights. So, these programs are forced to run with an elevation prompt on UAC-enabled systems.
It's not just the executable name either. If renaming the file does not solve the problem, the application might have these keywords in its version information too. Having the following will result in the same behavior:
[assembly: AssemblyTitle("Setup DVD Player")]
[assembly: AssemblyProduct("Instal President")] // Yes, even with the misspelling.
Easy way out is to rename the application and to avoid using these keywords.
Proper way out is including an application manifest in the executable.
Related
Has anyone ever run into an issue with .net 4.8 (c#) throwing "too long path" errors like below when run from a class library project. The same line of code is working fine for me if I run it from a windows forms project.
the error is below
"The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters"
The code I'm using to get the error is pretty simple. StrPath is a valid path that is say 350 chars long. ("c:\<350 Char path and filename>")
string a = Path.GetDirectoryName(strPath);
That's the simplest example, but it also happens when using any File or FileIO method like File and FileStream where I reference the long path.
Things I've tried
Most recommendations from https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file?redirectedfrom=MSDN
setting the long path registry key
Including app manifest with settings to recognize long paths. (there were two different types of these I found on the net, neither worked)
prefixing with "\\?\"
Looked at what mscorlibs are being referenced by both the windows forms and the exe calling the class library dll. Both were identical and referenced 4.8 libs.
Both projects succeed when I use a shorter path than 260. So it is really a path len issue I think. It just seems to behave as if I'm using an older version of .net when run from the class library.
I call the class library from within a native C++ app (its a com interop). I can also get it to happen if I make a class library with that code into an nunit text fixture and call it from nunit-x86.exe. So the code would be as below for that. And fails when calling GetDirectoryName
using System.Text;
using System.Threading.Tasks;
using NUnit.Framework;
using Omtool.Properties;
using System.Diagnostics;
using System.IO;
using OmXceedInterop;
using System.Windows.Forms;
namespace XceedTest
{
[TestFixture]
public class Class1
{
[Test]
public void Test()
{
string strPath = "C:\\Kit\\BlahServer\\Work\\CompoundFile\\Xceed\\2a0bb008-397b-476a-8e89-96caa7a11319\\HLCUVL1221104974\\THIS_NAME_IS_TOO_FRACKING_LONG_TO_BE_IN_ANY_WAY_USEFUL_YOU_SHOULD_BE_A_FRACKING_SHAMED_OF_YOURSELF_HLCUVL1221104974_Container Inspection_NANDA TILES,SL-DOCUMENTO CONTENEDOR-NEXP-220199-STYLE ACCESS-FLOOR DECOR-BAYTOWN TX-NO.1001367035.pdf";
int b = strPath.Length;
string a = Path.GetDirectoryName(strPath);
}
}
}
Again, the exact same lines of code work from the forms app but fail when called from the class library. There is something different about these two projects or perhaps the context under which they run that I'm just not understanding.
[EDIT]
It has to be the context. When I run my nunit class from the forms app, there is no path error. When I run that same assembly from nunit-x86.exe, I get the pathing error. It seems to depend on what's calling the class library as to whether I get the error or not
I updated my C# WPF application to use latest versions of NLog and NLog.Extensions.Logging.
It works everywhere except in this VMWare Horizons client where it crashes with this error:
$exception {"Attempt by method 'NLog.Extensions.Logging.NLogLoggerProvider..ctor(NLog.Extensions.Logging.NLogProviderOptions, NLog.LogFactory)' to access method 'NLog.LogManager.get_LogFactory()' failed."} System.MethodAccessException
This project is currently using NLog v4.5.11 and
NLog.Extensions.Logging v1.4
A previous version of my application which uses NLog v.4.4.12 and
NLog.Extensions.Logging v1.0 worked in this VM so i am trying to fall back to that. Then i'll work my way up the versions of these libraries.
More to follow soon... meanwhile, any insight into what might be causing this would be very welcome.
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var loggerFactory = new LoggerFactory();
var Logger = loggerFactory.CreateLogger<Program>();
loggerFactory.AddNLog();
Logger.LogDebug($"============{Environment.NewLine}");
Console.ReadLine();
}
}
}
You have a problem with your deployment. Your application is not using NLog ver. 4.5 (But some older version).
LogFactory-property became public with this: https://github.com/NLog/NLog/pull/2316
Maybe you have old NLog registered in Windows GAC ? (Global Assembly Cache)
Maybe try writing the typeof(NLog.LogFactory).Assembly-location using Console.WriteLine.
I'll add to answer https://stackoverflow.com/a/54557849/8081796
This issue is actual for Windows 8.
Get path to used NLog.dll:
typeof(NLog.LogFactory).Assembly.Location
If the path leads somewhere in C:\Windows\Microsoft.NET\assembly\GAC_MSIL then just delete this file
Thanks Stepan.
As I recall, it is not easy to delete a file from the GAC. And from what I have learned, not a good practice because it could break another application that depended on it.
Windows installer maintains a reference count of items in GAC, increasing the count with each install, reducing with each uninstall. If the count goes to 0, the dll is also removed from the GAC.
I uninstalled the application that put Nlog in the GAC. (It was another application that I had written long ago.) Then i modified the installer for that old app, ensured that it did not put it back in the GAC and re-installed it. And everything was well again.
I have an Inno Setup script where the desired form was too complicated to build entirely in Inno Setup itself, so I created a helper class library in .NET which contains a WinForms window with the things I need.
I open this WinForms window in Inno Setup by exposing the method with the Unmanaged Exports NuGet from Robert Giesecke.
This works perfectly on my development machine running Windows 10. It also works on a test server running Windows Server 2012 and 2016. When I try to run the setup on a Windows Server 2008R2 machine however, I am presented with the following error:
Sytem.ArgumentException: Font '?' cannot be found.
This is my Inno Setup script:
#define MyAppName "InnoTest"
#define MyAppVersion "1.0"
#define MyAppPublisher "Test"
#define MyAppURL "http://inno.test"
[Setup]
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={pf}\{#MyAppName}
DefaultGroupName={#MyAppName}
DisableProgramGroupPage=yes
OutputDir=C:\Users\Admin\Desktop\test_inno
OutputBaseFilename=test_inno_setup_x64
Compression=lzma/Max
SolidCompression=true
[Files]
Source: "C:\Users\Admin\Documents\Visual Studio 2017\Projects\InnoTestNet\InnoTestNet\bin\Release\InnoTestNet.dll"; DestDir: "{tmp}"; Flags: dontcopy
[Code]
procedure ShowTestForm(); external 'ShowTestForm#files:InnoTestNet.dll stdcall';
procedure InitializeWizard();
begin
ShowTestForm();
end;
and my C# code:
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using RGiesecke.DllExport;
namespace InnoTestNet
{
public class InnoTestNet
{
[DllExport("ShowTestForm", CallingConvention = CallingConvention.StdCall)]
public static void ShowTestForm()
{
try
{
var testForm = new TestForm();
testForm.ShowDialog();
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
I have reduced the WinForms window down to the bare minimum (just one label).
Things I have tried:
Embedding "Arial.otf" in the class library, loading the font at
runtime with PrivateFontCollection and setting the font on the
WinForm.
Using another font like Calibri or Tahoma
Changing the font of the InnoSetup installer itself (DefaultDialogFontName)
Executing "Application.EnableVisualStyles()"
The Windows Server 2008R2 environment is a fully updated clean install with .NET Framework 4.7.2 intalled.
The class library is targeted for .NET Framework 4.5.2.
I am using the Unicode version of InnoSetup 5.6.1.
edit
I found this interesting SO question:
Using SetDefaultDllDirectories breaks Font handling
It appears, when calling the "SetDefaultDllDirectories" function from the Windows API, font resolving might get broken.
When further tracking down the release notes of Inno Setup 5.5.9 it appears Inno Setup is indeed calling this problematic function.
Goal: Create a C# Assembly called TestDLL.dll that can be installed to any computer such that MS Access VBA can use it via COM.
Environment:
Windows 7 64-bit.
MS Office Professional Plus 2010 Version: 14.0.1753.5000 (64-bit).
Visual Studio 2010 Professional.
TestDLL.dll assembly code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace TestDLL
{
[ComVisible(true)]
[Guid("7CAAEF3F-F867-445B-B078-5837A833620A")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IGreeting
{
string SayHello();
}
[ComVisible(true)]
[ProgId("TestDLL.Greeting")]
[Guid("73D4187A-F71D-4E45-832A-6DD9F88CC59B")]
[ClassInterface(ClassInterfaceType.None)]
public class Greeting : IGreeting
{
[ComVisible(true)]
public string SayHello()
{
return "Hello, World!";
}
}
}
A WinForms project added to the solution successfully calls the SayHello() method.
TestDLL project properties:
Application / Target Framework - .NET Framework 4
Application / Assembly Information / Make assembly COM-visible: false (I only want certain public classes within the assembly to be COM-visible, not ALL public classes. Even though for this demo there's just one class and I do want it to be COM-visible. The code above should have taken care of that.)
Application / Assembly Information / Title and Description and Company and Product are all "TestDLL".
Build / Platform: Active (any CPU)
Build / Platform target: x86
Build / Register for COM interop: false (I don't want it to work on MY computer only but ALL computers. Thus I want to register the assembly when it is INSTALLED, not when it is BUILT.)
Signing / Sign the assembly: false (I want the assembly to live in the install folder, not in the GAC.)
A peek at AssemblyInfo.cs reveals:
[assembly: ComVisible(false)]
[assembly: Guid("6bf701f9-3953-43bb-a8af-1bdf7818af3c")]
The assembly is built.
Then a type library is created using the Visual Studio Command Prompt (run as Administrator) with this command:
tlbexp "C:\(path)\bin\Release\TestDLL.dll" /win32 /out:"C:\(path)\bin\Release\TestDLL.tlb"
A Visual Studio Installer project called SetupTestDLL is added to the solution.
On its File System tab, Application Folder, TestDLL.dll is added. This automatically also adds TestDLL.tlb.
Right-clicking TestDLL.dll in that Application Folder allows opening a properties window.
There, Register: vsdraCOM
When right-clicking TestDLL.tlb in that Application folder to get the properties window:
Register: vsdrfCOM
(I'm guessing that vsdraCOM means register the assembly and vsdrfCOM means register a file for COM.)
One more file is added to the Application folder: TestDLL.pdb.
SetupTestDLL is built.
Browsing to its output folder, reveals setup.exe and setupTestDLL.msi.
Right-click setup.exe and Run as administrator.
A dialog box displays the correct install path and the correct "Install for everyone" option.
The install completes successfully.
In the Control Panel / Programs and Features, TestDLL is now listed. Its publisher is listed as "XYZ". Where did that come from? Evidently from the "Manufacturer" property of the SetupTestDLL project's property window. I created that value only there in the entire solution.
In C:\Program Files (x86) there is now an "XYZ" folder, under which is a TestDLL folder, and in that are the three files.
Launch MS Access. Open an existing database and its existing code module.
From the Access code window toolbar, choose Tools / References.
TestDLL is found in the Available References listbox. Click its check box and click OK.
Click the Object Browser button on the code window toolbar.
is selected in a dropdown list. Change it to TestDLL.
The class "Greeting" is shown with its method "SayHello". So far, so good.
Close the Object Browser.
Create this procedure in the code module and try to run it.
Public Sub Test2()
' Dim o As New TestDLL.Greeting
' The above is early binding. It should also work
' since we set a reference.
Dim o As Variant
Set o = CreateObject("TestDLL.Greeting")
' The above is late binding.
Debug.Print o.SayHello()
Set o = Nothing
End Sub
Result:
Whether early or late bound,
ActiveX Component can't create object.
What's wrong?
I was just going to add a comment, but I don't have enough reputation points so I'll just post this as an answer and remove it if necessary.
I'm not familiar with Visual Studio Installer projects, so I'm not sure if it is registering the assembly correctly. Have you tried using regasm to register TestDLL? Something like:
regasm /codebase TestDLL.dll /tlb:TestDLL.tlb
64-bit MS Office cannot use a 32-bit COM DLL early bound, but with a reg hack involving DLLSurrogate, it can use it late-bound. I got that to work.
Trying to automate WHQL testing using the ONE AND ONLY document available on the subject: http://www.microsoft.com/whdc/devtools/wdk/dtm/dtm_dsso.mspx
I've played with the example code and am able to connect, list devices, etc. From there I've created a new project, a .NET 2.0 C# class:
using System;
using System.Reflection;
using System.IO;
using CookComputing.XmlRpc;
using Microsoft.DistributedAutomation.DeviceSelection;
using log4net;
class WhqlXmlRpcService : XmlRpcService
{
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public static DeviceScript deviceScript;
[XmlRpcMethod("connect")]
public Boolean Connect(String dtm)
{
Boolean retVal = false;
deviceScript = new DeviceScript();
try
{
deviceScript.ConnectToNamedDataStore(dtm);
retVal = true;
}
catch (Exception e)
{
Log.Debug("Error: " + e.Message);
}
return retVal;
}
}
I'm using XML-RPC.NET to create a server that is hosted by IIS (using ASP.NET 2.0). The DTM Studio is installed in C:\Inetpub\wwwroot\xmlrpc\bin, the same place where the target of my class goes, to assure there are no resolution issues with the dozen or so .dll's I reference (as instructed by the DSSO doc). I tried adding the necessary DSSO libraries to the GAC to avoid this, but not all of them have strong names. So, despite being able to see all the libraries it needs to link against (and the Studio app functions just fine installed in a non-standard location), attempting .ConnectToNamedDatastore("nameofDTM") still results in the following:
xmlrpclib.Fault: <Fault 0: 'Could not connect to the controller to retrieve information. Several issues can cause this error including missing or corrupt files from the installation, running the studio application from a folder other than the install folder, and running an application that accesses the scripting APIs from a folder other than the installation folder.'>
I'm accessing the scripting APIs from the installation folder, as it's the same dir as my web service .dll, and the files aren't corrupt, because if I stick an .exe with the DSSO sample code in that same directory I can see it connect just fine in the debugger.
I'm at the end of my rope with this, and have been unable to find a helpful source for DTM/DSSO info anywhere.
Anyone done anything similar in the past, or had any success automating their WHQL testing?
I was unable to get this to work using an ASP.NET web service .dll, however, I was able to access the DSSO API by making my XML RPC server available using the HttpListener class in .NET. If you deploy the target application into the same directory as DTM Studio, all works as expected.
For an example of how to use XML-RPC.NET with HttpListener, see:
http://www.cookcomputing.com/blog/archives/000572.html
Note: "ListenerService" has been incorporated into the latest versions of XML-RPC.NET since the time of the linked post above. It can be found under CookComputing.XmlRpc.XmlRpcListenerService