I create some method(this is only test method, to isolate problem from very very big system):
private void CompileHalloWorld()
{
System.Threading.Thread.Sleep((30000));
if (!Directory.Exists(_workingDir))
{
Directory.CreateDirectory(_workingDir);
}
Directory.SetCurrentDirectory(_workingDir);
var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });
var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, "foo.exe", true);
parameters.GenerateExecutable = true;
CompilerResults results = null;
try
{
results = csc.CompileAssemblyFromSource(parameters,
#"using System;
class Program {
public static void Main(string[] args) {
Console.WriteLine(""Hallo World!"");
}
}");
}
catch (Exception e)
{
int a = 2;
}
results.Errors.Cast<CompilerError>().ToList().ForEach(error => Console.WriteLine(error.ErrorText));
}
On 99% machines this method work good, but on one of machines is some issue. When server work some times (few days), something broke in Windows I think. Then, when I run CompileHalloWorld() from exe app all work fine, but when I run this method from simple empty service, after invoke CompileAssemblyFromSourceinvoke in results structure is no errors in collection, but csc.exe return exit code -1073741502... After reboot of server all work good again, but I can't restart server every day...
I try to find some solution in SO. I check in Task Manager and no csc.exe proces hang, no Visual Studio work, no VBCSCompiler.exe hangs...
Please help me.
Related
I have a Console application that is ran on the background. Its a simple server that built using NetMQ library and NLogger that works locally.
I ran the program using taskScheduler with the following command schtasks /create /sc ONSTART /tn "TheServer" /tr "C:\\Temp\TheServer.exe" /ru System
As you can se, now it will start every time the desktop is turned on and it will run as System (It means that we can see TheServer.exe is running as background through Task Manager)
Question:
My timeline was like the follows:
My PC was on on Friday morning (starting of Business day - 09:00 in the morning)
I didn't turn off my PC on Friday before I go back from work
Monday morning, I checked my PC and TheServer is already gone
Does anyone know why it happens and how to prevent it?
FYI, I write my code as follows
Program.cs
class Program
{
[STAThread]
static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();
...
static void Main(string[] args)
{
try
{
var inst = Server.GetInstance();
inst.Bind();
inst.Run();
}
catch (Exception e)
{
log.Error(e.Message);
log.Error(e.StackTrace);
throw;
}
}
}
Server.cs
class Server
{
private NetMQ.Sockets.ResponseSocket rSocket = new NetMQ.Sockets.ResponseSocket();
static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();
...
public void Bind()
{
try
{
//bind is only for the Responder or The Server
rSocket.Bind("tcp://127.0.0.1:32325");
}
catch (Exception e)
{
log.Error(e.Message);
log.Error(e.StackTrace);
throw;
}
}
public void Run()
{
while (true)
{
var message = server.ReceiveFrameString();
Console.WriteLine("Received {0}", message);
// processing the request
Thread.Sleep(100);
Console.WriteLine("Sending World");
server.SendFrame("World");
}
}
}
I wrap my code at Program.cs with try-catch. But nothing written in the log
Then
I tried to find some information at the Window's Event Viewer. But there are no related information why TheServer.exe stopped
Update:
Looks like I found what #PMF means.
Then one extra question. . .
Is there any way to do that through command prompt?
I tried to read https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/schtasks-create Looks like if I didn't set the /du when create the task, it will be forever (?). CMIIW
UPDATE
So yes, we decided to recreate this TheServer.exe as Windows Service. Thanks for your input and opinions.
I'm creating a little stupid service as a joke, is supposed to create an "invincible" txt on the desktop which gets recreated if deleted.
It works when debugged but when I install the service it doesn't create the txt.
I have :
execute the service with admin rights adding this line of code:
<PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
to the app.manifest).
I checked the "the authorize to interact whit desktop" checkmark on the service proprieties.
the code is working when I debug (i use Topshelf) but when I install the service it does not work.
the code which creates the txt(and the constructor):
public Invincible()
{
_timer = new Timer(3000) { AutoReset = true };
_timer.Elapsed += TimerElapsed;
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
string[] frase = new string[] {"NON PUOI RIMUOVERE QUESTA MALEDIZIONE <3"};
string curFile = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)+"/Invincible_Curse.txt";
string curFile2 = "C:/temp/Demos/Invincible_Curse.txt";
if (!File.Exists(curFile))
{
File.AppendAllLines(curFile, frase);
}
}
the Main:
static void Main(string[] args)
{
var exitCode = HostFactory.Run(x =>
{
x.Service<Invincible>(s =>
{
s.ConstructUsing(Invincible => new Invincible());
s.WhenStarted(Invincible => Invincible.Start());
s.WhenStopped(Invincible => Invincible.Stop());
x.SetServiceName("InvincibleService");
x.SetDisplayName("Invincible Service");
x.SetDescription("Cerca di sopravvivere");
});
});
int exitCodeValue = (int)Convert.ChangeType(exitCode, exitCode.GetTypeCode());
Environment.ExitCode = exitCodeValue;
}
thanks for the help.
Your code seems okay, even though you could do with a bit of a refactoring.
For example move around this part like this:
var exitCode = HostFactory.Run(x =>
{
x.Service<Invincible>(s =>
{
s.ConstructUsing(Invincible => new Invincible());
s.WhenStarted(Invincible => Invincible.Start());
s.WhenStopped(Invincible => Invincible.Stop());
});
x.SetServiceName("InvincibleService");
x.SetDisplayName("Invincible Service");
x.SetDescription("Cerca di sopravvivere");
});
Your issue is that, the windows service that you are running is using a different Windows user account, it's not the Windows user account which you use for logging in and using your PC. So their desktop paths are different. Every user account on Windows has a different desktop path.
To fix it, simply make the service log on using the account which you want the txt file to appear to.
I have been trying to diagnose a memory leak in a service which only appears on Windows 7/Server 2008 R2. I narrowed it down to where we are using Microsoft.Web.Administration.ServerManager to gather info about the apps in our site. I whittled it down to the console app below, which exhibits the same behavior. It might still be more complex than it needs to be, but I wanted to emulate the behavior of the service as much as possible.
I found a previous question here that was very similar and made the changes suggested in the answers. This appeared to reduce the rate of growth, but it still leaks significantly (under the comments "Original Test" I have commented out code that I changed based on those answers. the "Modified Test" comments indicate the changes I made. I didn't initially have the GC.Collect call in, and when I ran this on a Windows 10 system, it grew for quite some time before the garbage collection kicked in. With the GC.Collect call in place, it ran without growing on Win 10, but on Win 7 it made no difference.
I ran it under a profiler that indicated the memory being leaked was native, and that the leak was coming from nativerd.dll.
Has anyone encountered a problem like this? I'm new to C# and am still learning how Garbage Collection works, so I'm wondering if there is something I'm doing wrong?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Web.Administration;
namespace ServerManagerLeakTest
{
class Program
{
static void Main(string[] args)
{
Console.Write("Working.");
var me = new MyClass();
me.Run();
}
}
internal class MyClass
{
ServerManagerWrapper _smw = new ServerManagerWrapper();
public void Run()
{
while (true)
{
var t = Task.Run(async delegate
{
DoWork();
await Task.Delay(1000);
});
try
{
t.Wait();
}
catch (Exception e)
{
Console.Write("Main Exception: " + e.Message);
}
Console.Write(".");
}
}
public void DoWork()
{
try
{
var data = _smw.GetWebApps().ToList();
data.Clear();
}
catch (Exception e)
{
Console.Write("DoWork Exception: " + e.Message);
}
}
}
internal class ServerManagerWrapper
{
public List<int> GetWebApps()
{
List<int> result = new List<int>() { };
// Original Test
//
// using (var serverManager = new ServerManager())
// {
// foreach (var site in serverManager.Sites)
// {
// result.AddRange(GetWebApps(site));
// }
//}
// Modified Test
var serverManager = new ServerManager();
foreach (var site in serverManager.Sites)
{
result.AddRange(GetWebApps(site));
}
serverManager.Dispose();
serverManager = null;
System.GC.Collect();
return result;
}
private IEnumerable<int> GetWebApps(Site site)
{
// Original Test
//
//for (var application in site.Applications)
//{
// yield return application.GetHashCode();
//}
// Modified Test
List<int> result = new List<int>() { };
for (int i = 0; i < site.Applications.Count; i++)
{
result.Add(site.Applications[i].GetHashCode());
}
return result;
}
}
}
Answer provided in comments from #Lex Li.
Move the check to a separate process. Calling IIS REST API, PowerShell, or even appcmd and parse the result. Let the leak be out of your own service.
using IPC over local TCP to communicate from Client to a Server thread. The connection itself doesn't seem to be throwing any errors, but every time I try to make one of the associated calls, I get this message:
System.Runtime.Remoting.RemotingException: Could not connect to an IPC Port: The System cannot Find the file specified
What I am attempting to figure out is WHY. Because this WAS working correctly, until I transitioned the projects in question (yes, both) from .NET 3.5 to .NET 4.0.
Listen Code
private void ThreadListen()
{
_listenerThread = new Thread(Listen) {Name = "Listener Thread", Priority = ThreadPriority.AboveNormal};
_listenerThread.Start();
}
private void Listen()
{
_listener = new Listener(this);
LifetimeServices.LeaseTime = TimeSpan.FromDays(365);
IDictionary props = new Hashtable();
props["port"] = 63726;
props["name"] = "AGENT";
TcpChannel channel = new TcpChannel(props, null, null);
ChannelServices.RegisterChannel(channel, false);
RemotingServices.Marshal(_listener, "Agent");
Logger.WriteLog(new LogMessage(MethodBase.GetCurrentMethod().Name, "Now Listening for commands..."));
LogEvent("Now Listening for commands...");
}
Selected Client Code
private void InitializeAgent()
{
try
{
_agentController =
(IAgent)RemotingServices.Connect(typeof(IAgent), IPC_URL);
//Note: IPC_URL was originally "ipc://AGENT/AGENT"
// It has been changed to read "tcp://localhost:63726/Agent"
SetAgentPid();
}
catch (Exception ex)
{
HandleError("Unable to initialize the connected agent.", 3850244, ex);
}
}
//This is the method that throws the error
public override void LoadTimer()
{
// first check to see if we have already set the agent process id and set it if not
if (_agentPid < 0)
{
SetAgentPid();
}
try
{
TryStart();
var tries = 0;
while (tries < RUNCHECK_TRYCOUNT)
{
try
{
_agentController.ReloadSettings();//<---Error occurs here
return;
} catch (RemotingException)
{
Thread.Sleep(2000);
tries++;
if (tries == RUNCHECK_TRYCOUNT)
throw;
}
}
}
catch (Exception ex)
{
HandleError("Unable to reload the timer for the connected agent.", 3850243, ex);
}
}
If you need to see something I haven't shown, please ask, I'm pretty much flying blind here.
Edit: I think the issue is the IPC_URL String. It is currently set to "ipc://AGENT/AGENT". The thing is, I have no idea where that came from, why it worked before, or what might be stopping it from working now.
Update
I was able to get the IPC Calls working correctly by changing the IPC_URL String, but I still lack understanding of why what I did worked. Or rather, why the original code stopped working and I needed to change it in the first place.
The string I am using now is "tcp://localhost:63726/Agent"
Can anyone tell me, not why the new string works, I know that...but Why did the original string work before and why did updating the project target to .NET 4.0 break it?
I am working on a project in c# that using threading to initialize multiple calls to xcopy to copy user directories from one workstation to a network location.
When I run the program in debug mode, sometimes if I have a break-point BEFORE the program hits the calls to XCopy, and I stop the debugging with the stop button (in VS 2010), the program will then proceed to call the XCopy function, even though I stopped it from reaching the calls in the code. If I stop inside the foreach loop does the debugger continue to do the other foreach instances?
I know it sounds crazy, but has anyone else ever experienced this, or might you offer some suggestions that would correct this from happening?
A second issue with this is that when I run it from my Win7 machine accessing an XP machine in Firefox, the osInfo is correct, but when my boss runs it on his Win7 machine in IE, it doesn't work. It makes sense to me that the lines:
System.OperatingSystem osInfo = System.Environment.OSVersion;
if (dir_base.Exists && (osInfo.Platform == System.PlatformID.Win32NT)) //XP
Should be pulling the system that is running the code, not the network location's operating system type, but the if statement results in true when I run it and false when he does...
Here is my code:
public static void BuildSources_Targets(string Source, string str_Target )
{
//XP:
string str_basePath = Path.Combine(Source, "Documents and Settings");
var dir_base = new DirectoryInfo(str_basePath);
System.OperatingSystem osInfo = System.Environment.OSVersion;
if (dir_base.Exists && (osInfo.Platform == System.PlatformID.Win32NT)) //XP
{
foreach (var dir in dir_base.GetFileSystemInfos())
{
switch (dir.ToString())
{
case "administrator":
case "Administrator":
case "Default User":
case "All Users":
//Do nothing
break;
default:
string str_dir = dir.ToString();
//Handle XP App Data
//str_baseAndDirsPath = Path.Combine(dir_base.ToString(), str_dir, Environment.SpecialFolder.ApplicationData.ToString());
string str_baseAndDirsPath = Path.Combine(dir_base.ToString(), str_dir, "Application Data");
DirectoryInfo dir_baseAndDirs = new DirectoryInfo(str_baseAndDirsPath);
if (dir_baseAndDirs.Exists)
{
string str_Destination = Path.Combine(str_Target, str_dir, "Application Data");
ProcessXcopy(str_baseAndDirsPath, str_Destination);
}
//Handle XP Documents
str_baseAndDirsPath = Path.Combine(dir_base.ToString(), str_dir, "My Documents");
dir_baseAndDirs = new DirectoryInfo(str_baseAndDirsPath);
if (dir_baseAndDirs.Exists)
{
string str_Destination = Path.Combine(str_Target, str_dir, str_dir + " Documents");
ProcessXcopy(str_baseAndDirsPath, str_Destination);
}
break;
} //end of switch
} //end of foreach
} //end of dir_base.exists
//it continues from here...but that's enough to illustrate my problem...