What does mono-io-layer-error (2) mean, starting a process in Unity? - unity3d

Context is Unity, trying to start a new external process. Code looks like this:
var startinfo = new ProcessStartInfo {
FileName = RootPath + Executable,
WorkingDirectory = RootPath,
UseShellExecute = true,
WindowStyle = Visible ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden,
};
try {
_process = Process.Start(startinfo);
return true;
} catch (Exception ex) {
_global.Fail($"Unable to start engine {startinfo.FileName}.\n{ex.ToString()}");
return false;
}
This works just fine in the Editor, but Build&Run fails with the following error:
System.ComponentModel.Win32Exception (0x80004005): mono-io-layer-error (2)
at System.Diagnostics.Process.StartWithShellExecuteEx (System.Diagnostics.ProcessStartInfo startInfo) [0x00102] in <3df7f9ca50404bbc8bd4e7b954e70293>:0
at System.Diagnostics.Process.Start () [0x00032] in <3df7f9ca50404bbc8bd4e7b954e70293>:0
at (wrapper remoting-invoke-with-check) System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start (System.Diagnostics.ProcessStartInfo startInfo) [0x0001b] in <3df7f9ca50404bbc8bd4e7b954e70293>:0
at ServerManager.StartServer () [0x00049] in <5143145dfb5b4093ac2347595a160b5c>:0
What does it mean? I can find nothing like it on the Web.
My guess is that the feature is perhaps not supported in the built version, but I have no way of finding out for sure or where to look for alternative approaches. At the end of the day all I really need is a way to launch an external process from a built Unity project.

This is a rather peculiar error, it might be a Unity bug. I've noticed that this error occurs when you usually try to concatenate or combine paths in the "FileName". The methods used for finding or combining paths dynamically are seem to be causing this problem. In my case, I was trying to find the path like this:
FileName = Directory.GetCurrentDirectory() + #"\SBERT\dist\SBERT\SBERT.exe",
However, I have found a workaround to this problem by assigning a fully hard-coded path in the "FileName" like:
FileName = #"C:\SBERT\dist\SBERT\SBERT.exe",
Hope this helps for someone, as there is no information about this error on the internet.

Related

How to use named object in macOS to limit app instances?

I need to preface this by saying that I'm coming from years of developing on Windows. This time I'm developing the UI for my macOS app using SwiftUI. The goal is to allow only one instance of the app, depending on where it's started from. For instance, if you copy the app into:
/Users/me/Documents/MyAppCopy/MyApp.app
and to:
/Users/me/Documents/MyApp.app
There should be only two instances of the app allowed, each from those respective locations.
On Windows I would use a named kernel object, say a named event, create it when the app starts and see if it already existed. If so, I will quit the app. Then when the first instance of the app closes, the named event is destroyed by the system automatically.
So I thought to try the same on macOS, but evidently Linux/BSD treats named objects differently.
If I do get the name of the object by calling:
var objName : Bundle.main.bundlePath
IsAnotherInstanceRunning(objName, objName.lengthOfBytes(using: String.Encoding.utf8))
and then using C, remove slashes from it, and use it in a named semaphore:
bool IsAnotherInstanceRunning(const char* pBundlePath, size_t szcbLnPath)
{
bool bResult = false;
char* pName = (char*)malloc(szcbLnPath + 1);
if(pName)
{
memcpy(pName, pBundlePath, szcbLnPath);
pName[szcbLnPath] = 0;
//Remove slashes
int cFnd = '/';
char *cp = strchr(pName, cFnd);
while (cp)
{
*cp = '_';
cp = strchr(cp, cFnd);
}
//Create if doesn't exist, and return an error if it exists
sem_t *sem = sem_open(pName, O_CREAT | O_EXCL, 0644, 0);
if(sem == SEM_FAILED)
{
//Failed, see why
int nErr = errno;
if(nErr == EEXIST)
{
//Already have it
bResult = true;
}
}
free(pName);
}
return bResult;
}
Assuming that the path name isn't too long (this is an issue, but it is irrelevant to this question) - the approach above works, but it has one downside.
If I don't close and remove the name semaphore with:
sem_close(sem);
sem_unlink(pName);
It stays in the system if the instance of my app crashes. Which creates an obvious problem for the code above.
So how would you do this on Linux/macOS?
To prevent/abort the start of an app while another instance is running, you can also use high-level AppKit stuff (we do this in one of our apps and it works reliably).
Use NSWorkspace.runningApplications to get a list of, well, the currently running applications. Check this list, and filter it for the bundleIdentifier of your app. You can then also check the bundleURL to decide whether it's OK to start the current app, which seems to be what you want to do. See also NSRunningApplication.current to get the informations about your current process.
(You can do [otherRunningApplication isEqual:NSRunningApplication.current] to check/filter the current process.)
Do this check in your applicationWillFinishLaunching or applicationDidFinishLaunching method.

"cd : Cannot find path 'D:\mnt\d\VS Code\' because it does not exist" error in VS Code

Here's a picture of my terminal-
https://i.stack.imgur.com/pkZNG.png
#include<iostream>
int main ()
{
std::cout<< "Hello";
return 0;
}
Please try this and give me the result
OR
Sometimes VS cant finds the solution path due to space in path
try to create a new solution and give it the address of :
D:\Dev\My_Cool_App\
Instead of
D:\Dev\My Cool App

How can I replicate New-SmbGlobalMapping in C# code?

I am writing a service which controls docker containers. I want to have the mounted volume as an Azure share, and thus need to use the SMB Global Mapping. If I use the usual WNetAddConnection2A then I can mount the share just fine in my code, but the containers cannot see it as it is not "global". I can't find source for the PowerShell New-SmbGlobalMapping command (is there a way to see it?) and I can't find a suitable API to call. I hope someone knows the magic incantation I can put in my .NET code.
I can't find source for the PowerShell New-SmbGlobalMapping command
(is there a way to see it?) and I can't find a suitable API to call. I
hope someone knows the magic incantation I can put in my .NET code.
PowerShell uses WMI
In your case, it calls
Create method of the MSFT_SmbMapping class (MSFT_SmbGlobalMapping exactly)
You can use WMI Code Creator to generate/test C# code
EDIT : Test with PowerShell.Create
Test as Admin ("requireAdministrator" in manifest) on Windows 10
Test code (C#, VS 2015) =>
// PowerShell calls CredUIPromptForCredentialsW to display the User/Password dialog (you can call it with P/Invoke if needed)
string sUser = "user#provider.com";
string sPassword = "myPassword";
System.Net.NetworkCredential networkCredential = new System.Net.NetworkCredential(sUser, sPassword, null);
System.Security.SecureString securePassword = new System.Security.SecureString();
foreach (var c in networkCredential.Password)
securePassword.AppendChar(c);
// Add reference to :
// C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll
// Add :
// using System.Management.Automation;
PSCredential psCredential = new PSCredential(networkCredential.UserName, securePassword);
// Error handling must be improved : if I pass an invalid syntax for "RemotePath" or not launched as Admin,
// nothing happens (no error, no result) (on Windows 10)
string sLocalPath = "Q:";
string sRemotePath = "\\\\DESKTOP-EOPIFM5\\Windows 7";
using (var ps = PowerShell.Create())
{
ps.AddCommand("New-SmbGlobalMapping");
ps.AddParameter("LocalPath", sLocalPath);
ps.AddParameter("RemotePath", sRemotePath);
ps.AddParameter("Credential", psCredential);
//ps.AddParameter("RequireIntegrity", false);
//ps.AddParameter("RequirePrivacy", false);
try
{
System.Collections.ObjectModel.Collection<PSObject> collectionResults = ps.Invoke();
foreach (PSObject psObl in collectionResults)
{
Console.WriteLine("Status : {0}", psObl.Members["Status"].Value.ToString());
Console.WriteLine("Local Path : {0}", psObl.Members["LocalPath"].Value.ToString());
Console.WriteLine("Remote Path : {0}\n", psObl.Members["RemotePath"].Value.ToString());
}
}
catch (ParameterBindingException pbe)
{
System.Console.WriteLine("\rNew-SmbGlobalMapping error : {0}: {1}",
pbe.GetType().FullName, pbe.Message);
}
}
// To get and remove the test mapping in PowerShell :
// Get-SmbGlobalMapping
// Remove-SmbGlobalMapping -RemotePath "\\DESKTOP-EOPIFM5\Windows 7" -Force

NPAPI plug-in in safari can not call js function?

all.I want to call a js function to show something in my plugin.This is my code
NPObject* npwindow = NULL;
NPError ret = browser->getvalue(mInstanceForJS, NPNVWindowNPObject, &npwindow);
if (ret != NPERR_NO_ERROR)
return ;
// Get window object.
NPVariant windowVar;
NPIdentifier winID = browser->getstringidentifier("window");
bool bRet = browser->getproperty(mInstanceForJS, npwindow, winID, &windowVar);
if (!bRet)
{
browser->releaseobject(npwindow);
return ;
}
NPObject* window = NPVARIANT_TO_OBJECT(windowVar);
NPVariant voidResponse;
NPVariant elementId;
STRINGZ_TO_NPVARIANT([info UTF8String], elementId);
NPVariant args[] = {elementId};
NPIdentifier funcID= browser->getstringidentifier([funName UTF8String]);
bRet = browser->invoke(mInstanceForJS, window, funcID, args, 1, &voidResponse);
browser->releasevariantvalue(&windowVar);
when called bRet = browser->invoke(mInstanceForJS, window, funcID, args, 1, &voidResponse);,Safari can not responsed.Is there any errors?
npwindow is already the window object; you're effectively querying for "window.window". Granted, I don't know why this wouldn't work, but it seems a little weird.
That's problem #1.
Problem #2 is that you're using STRINGZ_TO_NPVARIANT to store the result of UTF8String. STRINGZ_TO_NPVARIANT doesn't copy the memory, so you could be in trouble if the function wanted to hang onto that string, since the string returned by that will be freed when your autorelease pool cycles. Of course, that could also be a memory leak. Either way, the correct way to pass a string to the browser is to allocate memory for it using NPN_MemAlloc and then copy the string in. Then pass that pointer to the browser. See http://npapi.com/memory for more info.
Problem #3 is that you haven't given us any idea of when you are running this code; it's quite possible that you are trying to run this code too early in the plugin or page lifecycle and thus it may not work because of that.
Then there is another question: What do you mean by "Safari can no responsed"? Forgetting the grammatical error, I'm not sure what you mean by this. Does it hang? is bRet false? Does your computer suddenly get encased in ice, thus halting all processing? If the above is not helpful, please answer these questions and I'll try again.

How to execute the code generated by codeDom?

I just generated the .cs file using codeDom. Can someone explain how do I execute it?
The code below will allow you to compile the code using the codedom and then you can show the user if the code compiled correctly or not. It even creates a DLL as well.
Thanks
Alex
// Store provider from the method into a object, Default is CSharpCodeProvider**
CodeDomProvider provider = this.GetCurrentProvider();
// Configure a CompilerParameters that links System.dll**
String[] referenceAssemblies = { "System.dll", "System.Data.Linq.dll", "System.Web.dll","System.XML.dll","System.ComponentModel.DataAnnotations.dll", "System.Data.dll", _mvcLocation };
CompilerParameters cp = new CompilerParameters(referenceAssemblies, this.fileLocation + this.fileName + ".dll", false);
// Generate an executable rather than a DLL file.**
cp.GenerateExecutable = true;
// Invoke compilation.**
CompilerResults _results = provider.CompileAssemblyFromFile(cp, this.fileLocation + this.fileName + "." + this.extention);
It's not quite that simple. See here for a primer. Basically the CodeDom supports scenarios such as code generation and dynamic compilation. So .cs files created with the CodeDom are not executables in the usual sense.