FileNotFoundException when using one-click install - c#

What Happens?
I have been having an issue on this now for the past week and I feel like i get closer and closer each day but can't put my finger on what it is.
I have purchased a license of a Third-Party program called 'Streamcoders' (lets you encoder a live stream). When installing this program it gives you (as far as i know) an x86 and x64 version of two .dll's 'MediaBase' and 'MediaSuite'. I have added the x86 version into my references as this is the one I need.
The properties of these dll's are :
Embed Interop Types = false.
Copy Local = true.
Aliases = global.
Specific Version = false.
So i go to publish my application. I specify the location, and then specify that i want the user to install the application from a Web Site. This all works and the application is installed.
I go to the clients machine and install the application and I get an error:
System.IO.FileNotFoundException: Could not load file or assembly 'MediaSuite.dll' or one of its dependencies. The specified module could not be found.
My Tests + Code
So when looking through my code I tried to add MessageBox.Show(""); to pin-point where the error occurs.
So on my Login page constructor, i call a method CheckUserRegistry():
try
{
if (Registry.GetValue("HKEY_CURRENT_USER", "URL", "").ToString() == string.Empty)
{
//User has not used the application before.
MessageBox.Show("NO URL FOUND");
return false;
}
else
{
MessageBox.Show("GENERATE");
//User has used the application before and is generating that user a session GUID.
Global.podiaClient = new podiaPublish.PublishClient();
Global.podiaClient.Endpoint.Address = new System.ServiceModel.EndpointAddress(string.Format(Registry.GetValue("HKEY_CURRENT_USER", "URL", "").ToString() + "/wcf/publish.svc"));
//Global.podiaSession = Global.podiaClient.Login(Registry.GetValue("HKEY_CURRENT_USER", "UID", "").ToString(), Global.Decrypt(Registry.GetValue("HKEY_CURRENT_USER", "PWD", "").ToString()));
Global.podiaSession = Global.podiaClient.Login(Registry.GetValue("HKEY_CURRENT_USER", "UID", "").ToString(), Registry.GetValue("HKEY_CURRENT_USER", "PWD", "").ToString());
return true;
}
}
catch (Exception ex)
{
//Global.HandleError(ex);
MessageBox.Show("here");
MessageBox.Show(ex.InnerException.ToString());
return false;
}
It successfully hits the MessageBox.Show("GENERATE"); and then after that seems to hit the catch and displays the error.
If i comment out the lines below the code does not error. podiaPublish is a Service Reference in my project.
Global.podiaClient = new podiaPublish.PublishClient();
Global.podiaClient.Endpoint.Address = new System.ServiceModel.EndpointAddress(string.Format(Registry.GetValue("HKEY_CURRENT_USER", "URL", "").ToString() + "/wcf/publish.svc"));
Global.podiaSession = Global.podiaClient.Login(Registry.GetValue("HKEY_CURRENT_USER", "UID", "").ToString(), Registry.GetValue("HKEY_CURRENT_USER", "PWD", "").ToString());
Does anyone have any clue as to what is going on?

Related

ServerManager fails with 0x80040154 in c# Winforms app creating simple web application in IIS

I am writing a small app that installs IIS and configures a website before deploying the files to it.
On a freshly reset Windows 10, the first attempt always fails with the 0x80040154 COM+ component failure as documented in This question
I looked at the version I am using and it is the latest and correct one for .net standard (4.8) and not the one meant for .net core
When I press the button to rerun the function it always finishes correctly. I tried using a retry routine, and it fails on each retry, yet runs fine again when the button is pressed. The reason for this I assume is that the server manager object isn't disposed when it hits the catch block since its in a using statement.
I can work around that, but I really want to understand the issue and make a permanent fix.
My routine simply creates a website in IIS and creates an app pool to assign to it.
And it is running with elevated privileges
For reference:
Machine is Windows 10 latest from the downloadable media creator.
Microsoft.Web.Administrator version is 7.0.0.0
App is .net 4.8 standard windows forms
using (var serverManager = new ServerManager())
{
string iisrootdir = drive;
//Check for inetpub/wwwroot
if (!Directory.Exists(iisrootdir)) //Check for Drive D
{
iisrootdir = #"C:\";
}
string iiscmsdir = Path.Combine(iisrootdir, "webdir", "appdir");
if (!Directory.Exists(iiscmsdir))
Directory.CreateDirectory(iiscmsdir);
var settings = new ApplicationSettings();
settings.ReadFromFile();
settings.CMSPATH = iiscmsdir;
settings.SaveToFile();
try
{
string poolName = "DefaultAppPool";
if (serverManager.Sites.Count > 0)
{
Site myDefualtWebsite = serverManager.Sites[0];
if (myDefualtWebsite != null)
{
OnRaiseInstallEvent(new InstallEventArgs("CreateWebsite", ProcessState.Started,
"Remove Default Website"));
serverManager.Sites.Remove(myDefualtWebsite);
serverManager.CommitChanges();
}
}
if (!WebsiteExists("sitename"))
{
mySite.ServerAutoStart = true;
}
Site site = serverManager.Sites["sitename"];
if (!AppPoolExists(poolName))
{
serverManager.ApplicationPools.Add(poolName);
}
ApplicationPool apppool = serverManager.ApplicationPools[poolName];
apppool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
apppool.ManagedRuntimeVersion = "";
serverManager.Sites["sitename"].ApplicationDefaults.ApplicationPoolName = poolName;
foreach (var item in serverManager.Sites["sitename"].Applications)
{
item.ApplicationPoolName = poolName;
}
serverManager.CommitChanges();
apppool.Recycle();
serverManager.CommitChanges();
}
catch (Exception ex)
{
if (ex.Message.Contains("80040154") && errorCount < 4)
{
if (serverManager != null)
serverManager.Dispose();
errorCount++;
OnRaiseInstallEvent(new InstallEventArgs("CreateWebsite", ProcessState.Started,
"Error encountered with COM+ object, trying again: " + errorCount));
CreateWebsite(#"D:\");
}
else
{
if (serverManager != null)
serverManager.Dispose();
errorCount = 0;
OnRaiseErrorEvent(new InstallErrorEventArgs("CreateWebsite", ProcessState.Error, ex));
return false;
}
}
finally
{
serverManager?.Dispose();
}
Thanks for the help Guys. I found the problem.
DISM was running in its own thread. The Process object exited the moment it launched. My function was then attempting to configure IIS before it had finished installing.

Tfs Check-in using PendAdd: The array must contain at least one element

So I'm having a problem with automating my code to check-in files to TFS, and it's been driving me up the wall! Here is my code:
string location = AppDomain.CurrentDomain.BaseDirectory;
TfsTeamProjectCollection baseUserTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection);
IIdentityManagementService ims = baseUserTpcConnection.GetService<IIdentityManagementService>();
TeamFoundationIdentity identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, #"PROD1\JR", MembershipQuery.None, ReadIdentityOptions.None);
TfsTeamProjectCollection impersonatedTpcConnection = new TfsTeamProjectCollection(uriToTeamProjectCollection, identity.Descriptor);
VersionControlServer sourceControl = impersonatedTpcConnection.GetService<VersionControlServer>();
Workspace workspace = sourceControl.CreateWorkspace("MyTempWorkspace", sourceControl.AuthorizedUser);
String topDir = null;
try
{
Directory.CreateDirectory(location + "TFS");
String localDir = location + "TFS";
workspace.Map("$/Automation/", localDir);
workspace.Get();
destinationFile = Path.Combine(localDir, Name + ".xml");
string SeconddestinationFile = Path.Combine(localDir, Name + ".ial");
bool check = sourceControl.ServerItemExists(destinationFile, ItemType.Any);
PendingChange[] pendingChanges;
File.Move(sourceFile, destinationFile);
File.Copy(destinationFile, sourceFile, true);
File.Move(SecondsourceFile, SeconddestinationFile);
File.Copy(SeconddestinationFile, SecondsourceFile, true);
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
else
{
workspace.PendEdit(destinationFile);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
and the problem is that whenever it's NEW files (PendEdit works correctly when the files already exist in TFS) that my code is attempting to check in, and it runs through this code:
if (check == false)
{
workspace.PendAdd(localDir,true);
pendingChanges = workspace.GetPendingChanges();
workspace.CheckIn(pendingChanges, Comments);
}
The files, instead of being in the included changes in pending changes, are instead in the excluded changes like so:
and when the line that actually does the check-in runs, I'll get a "The array must contain at least one element" error, and the only way to fix it is to manually add those detected changes, and promote them to included changes, and I simply can't for the life of me figure out how to do that programatically though C#. If anyone has any guidance on what direction I should take for this, I would really appreciate it! Thank you!
Edit: I've also discovered another way to solve this by reconciling the folder, which also promotes the detected changes, but again the problem is I can't seem to figure out how to program that to do it automatically.
I know that running the visual studio developer command prompt, redirecting to the folder that this mapping is in, and the running "tf reconcile /promote" is one way, but I can only automate that as far as the /promote part, because that brings up a toolbox that a user would have to input into, which defeats the purpose of the automation. I'm at a loss.
Next Edit in response to TToni:
Next Edit in response to TToni:
I'm not entirely sure if I did this CreateWorkspaceParameters correctly (see picture 1), but this time it gave the same error, but the files were not even in the excluded portions. They just didn't show up anywhere in the pending changes (see picture 2).
Check this blog:
The workspace has a method GetPendingChangesWithCandidates, which actually gets all the “Excluded” changes. Code snippet is as below:
private void PendChangesAndCheckIn(string pathToWorkspace)
{
//Get Version Control Server object
VersionControlServer vs = collection.GetService(typeof
(VersionControlServer)) as VersionControlServer;
Workspace ws = vs.TryGetWorkspace(pathToWorkspace);
//Do Delete and Copy Actions to local path
//Create a item spec from the server Path
PendingChange[] candidateChanges = null;
string serverPath = ws.GetServerItemForLocalItem(pathToWorkspace);
List<ItemSpec> its = new List<ItemSpec>();
its.Add(new ItemSpec(serverPath, RecursionType.Full));
//get all candidate changes and promote them to included changes
ws.GetPendingChangesWithCandidates(its.ToArray(), true,
out candidateChanges);
foreach (var change in candidateChanges)
{
if (change.IsAdd)
{
ws.PendAdd(change.LocalItem);
}
else if (change.IsDelete)
{
ws.PendDelete(change.LocalItem);
}
}
//Check In all pending changes
ws.CheckIn(ws.GetPendingChanges(), "This is a comment");
}

SharePoint ClientContext.ExecuteQuery works in c# application but crashes in DLL

I have written C# code to search for specific file types in SharePoint lists within a site and display the file names in a listview.
The code works perfectly well in a C# windows application, but when it is compiled into a C# DLL and called from a Delphi2007 application it crashes when it hits the first call to ClientContext.ExecuteQuery(). There is no exception or error message - the Delphi application just stops running.
The really weird part is that my Delphi test application has a web browser component, and if I use that to navigate to the top level list on the site the DLL then works OK.
The question therefore is why does the first ExecuteQuery call fail in the DLL if I haven't logged on to the site first?
This is the C# code:
public void ListFiles()
{
string LContains = "<Contains><FieldRef Name='FileLeafRef'/> <Value Type ='Text'>{0}</Value></Contains>";
string LNotEqual = "<Contains><FieldRef Name='FileLeafRef'/><Value Type ='Text'>{0}</Value></Contains>";
string LWhereQuery = "";
switch (comboFileType.SelectedIndex)
{
case 0: LWhereQuery = string.Format(LContains, ".DOC"); break;
case 1: LWhereQuery = string.Format(LContains, ".PDF"); break;
case 2: LWhereQuery = string.Format(LNotEqual, "xxxx"); break;
}
Uri LUri = new Uri(SharePointURL);
using (SP.ClientContext LContext = new SP.ClientContext(SharePointURL))
{
System.Net.CredentialCache cc = new System.Net.CredentialCache();
if (!string.IsNullOrEmpty(Domain))
cc.Add(LUri, AuthenticationType, new System.Net.NetworkCredential(UserName, Password, Domain));
else
cc.Add(LUri, AuthenticationType, new System.Net.NetworkCredential(UserName, Password));
LContext.Credentials = cc;
LContext.AuthenticationMode = SP.ClientAuthenticationMode.Default;
var LWeb = LContext.Web;
lvItems.BeginUpdate();
try
{
try
{
SP.List LList = LWeb.Lists.GetByTitle(DefaultListName);
SP.CamlQuery LQuery = new SP.CamlQuery();
LQuery.ViewXml = "<View Scope='RecursiveAll'><Query><Where>"
+ LWhereQuery
+ "</Where></Query><RowLimit> 30 </RowLimit></View>";
SP.ListItemCollection LItems = LList.GetItems(LQuery);
LContext.Load(LItems);
LContext.ExecuteQuery(); **<<<< Crash happens here**
foreach (SP.ListItem LItem in LItems)
{
SP.File LFile = LItem.File;
LContext.Load(LFile);
LContext.ExecuteQuery();
var LViewItem = new ListViewItem();
try { LViewItem.Text = LFile.Name; }
catch { LViewItem.Text = "!Error"; }
try { LViewItem.SubItems.Add(LFile.TimeLastModified.ToString()); }
catch { LViewItem.SubItems.Add("!Error"); }
if (LFile.CheckOutType != Microsoft.SharePoint.Client.CheckOutType.None)
{
try { LViewItem.SubItems.Add(LFile.CheckedOutByUser.LoginName); }
catch { LViewItem.SubItems.Add("!Error"); }
}
else
LViewItem.SubItems.Add("Not checked out.");
try { LViewItem.Tag = LFile.ServerRelativeUrl; }
catch { LViewItem.Tag = "!Error"; }
lvItems.Items.Add(LViewItem);
}
}
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex);
}
}
finally
{
lvItems.EndUpdate();
}
}
The code is in the .cs of a dialog form in the DLL. The form displays as it should and the crash only happens when I click a button to do the search.
I put some debug code in to check all the string params etc. (by writing them to a text file) and they are all OK.
I tried debugging the DLL from VS by specifying the D2007 app as the 'startup external program' but I can't get breakpoints to work and at the point where it crashes it says: An unhandled exception of type 'System.StackOverflowException' occurred in Microsoft.SharePoint.Client.Runtime.dll and suggests I might have an infinite recursive call but, as mentioned earlier, the code all works perfectly if I have already logged into the site and browsed to the top level list, so i don't think it is a recursive call.
UPDATE: I got the debugging to work by copying the Delphi exe to the same directory as the DLL.
I've tried using the ExceptionHandlingScope but it hasn't helped. This is how it looks when it crashes:
The scope has no exception and the errormessage is blank. I tried a few connotations of what was inside the scope but to no avail.
The whole code block is in a try..catch and I've tried wrapping the ExecuteQuery line in it's own try..catch as well, but nothing catches it. The app crashes out every time when I hit continue.
I've also tried putting an execute query before loading the web but it still crashes out.
I'm thinking this has to be something to do with credentials? If I deliberately put the wrong username I get a polite '401 Unauthorized' back and no crash. And if I'm already logged in it doesn't crash either?
After trying the C# test application I tried the same with Delphi XE8 and that also worked, so in the end I've resorted to writing an intermediate DLL in XE8.
I noticed that when importing the TLB from the C# DLL into XE8 it behaved differently from D2007 in that it complained about other missing TLB's when building - notably the system.windows.forms library (and some dependencies). I'm not sure if this has any bearing on XE8 working and D2007 failing, but hopefully it well help anyone else needing a workaround.

SharpShell server .dll NOT signed

I need to develop a Shell Context Menu extension that references some other custom assemblies... I don't want to assign a Strong Name Key to those custom assemblies!
The guide I followed to do this uses the SharpShell project and illustrates how to sign (but does not expalins why) the assembly... and this is my problem: if I sign my final .dll then I have many errors during my project's building phase, because some assemblies my project references are not strongly named ("Referenced assembly does not have a strong name").
In general, googling about the C# Shell Extension implementation, all best tutorials I found sign the final assembly... is it mandatory?
Without signing the assembly ServerManager.exe returns this error: "The file 'XYZ.dll' is not a SharpShell Server".
Finally I've solved my troubles... the SharpShell.dll file obtained through NuGet was a different version of the ServerManager.exe ones.
Uninstalling the SharpShell NuGet package and directly referencing the SharpShell.dll you find inside the ServerManager folder was my solution!
Moreover, I was looking between the article comments... please read this question.
You don't need to use old DLL.
Please use this code directly, without using ServerManager.exe.
private static ServerEntry serverEntry = null;
public static ServerEntry SelectedServerEntry
{
get
{
if (serverEntry == null)
serverEntry = ServerManagerApi.LoadServer("xxx.dll");
return serverEntry;
}
}
public static ServerEntry LoadServer(string path)
{
try
{
// Create a server entry for the server.
var serverEntry = new ServerEntry();
// Set the data.
serverEntry.ServerName = Path.GetFileNameWithoutExtension(path);
serverEntry.ServerPath = path;
// Create an assembly catalog for the assembly and a container from it.
var catalog = new AssemblyCatalog(Path.GetFullPath(path));
var container = new CompositionContainer(catalog);
// Get the exported server.
var server = container.GetExport<ISharpShellServer>().Value;
serverEntry.ServerType = server.ServerType;
serverEntry.ClassId = server.GetType().GUID;
serverEntry.Server = server;
return serverEntry;
}
catch (Exception)
{
// It's almost certainly not a COM server.
MessageBox.Show("The file '" + Path.GetFileName(path) + "' is not a SharpShell Server.", "Warning");
return null;
}
}
Install code:
ServerRegistrationManager.InstallServer(SelectedServerEntry.Server, RegistrationType.OS64Bit, true);
Register code:
ServerRegistrationManager.RegisterServer(SelectedServerEntry.Server, RegistrationType.OS64Bit);

Simple ASMX WebService and DLL not loaded

I've a problem running an ASMX Web Service. I'm Calling a DLL from a method (AceptaTools.dll) and this DLL load ca4xml.dll.
AceptaTools.dll has been registered with REGSVR32. But ca4xml.dll Can't.
When i Invoke the service:
_objURL = _CA4XML.GetLastResponse();
i get a message "ca4xml.dll not loaded".
Looking al Dependency Walker:
Here both files in detail:
Both DLL are in BIN folder and my project run as x86... Why can't load?? Please help.
[WebMethod]
public string Send(string Ip, string Puerto, string NroDocumento, string TipoDocumento, string Comando, string Impresora, string Linea)
{
try
{
int _Result = 0;
string _Null = "";
string _objURL;
//Config Capsula
string serverConfig = "cfg|" + Ip.ToString() + "|" + Puerto.ToString() + "|10";
//Impresora FACTURA,1 por Defecto.
if (string.IsNullOrEmpty(Impresora)) { Impresora = "FACTURA,1"; }
if (string.IsNullOrEmpty(NroDocumento)) { NroDocumento = "0"; }
if (string.IsNullOrEmpty(Comando)) { Comando = "generar"; }
//Nuevo CAXML Cliente
AceptaTools.CA4XML_Client _CA4XML = new CA4XML_Client();
_Result = _CA4XML.Send(ref serverConfig, ref NroDocumento, ref Comando, ref Impresora, ref Linea, out _Null);
if (_Result != 0)
{
_objURL = _CA4XML.GetLastResponse(); //Get URL
return _objURL.ToString();
}
else
{
return "Error";
}
}
catch (Exception ex)
{
return ex.Message.ToString();
}
}
}
Did you make sure that the ca4xml.dll is deployed properly? Since I guess it is not referenced as .NET assembly the VS will treat it like a normal file and you will need to specifically tell VS to include it when deploying.
Do the following steps to check whether deployment has been setup properly:
Open the Solution Explorer -> Got to the ca4xml.dll -> Right click -> Select Properties -> Set Build Action = None & Copy to Output = Always
Also in addition to the Dependency Walker I suggest to use Process Monitor. When you use the file access view (disregarding registry changes etc.) you can see all the locations where a process tries to load a dll from. Afterwards you can make sure that the dll you are missing is in one of the listed locations, here is the link:
http://technet.microsoft.com/en-us/sysinternals/bb896645
When you do not load DLL in the program because you need to update some things .
you can update project in nuget manager

Categories