|
You're welcome!
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Hi y'all. I've noticed since switching to Windows 8 that a custom service that I wrote never really gets shut down because of the Windows 8 fast startup feature. I would like to still have my service do its shutdown processing even during a hybrid shutdown. So my question is: When Windows 8 does a hybrid shutdown, is there some new message I can receive in my service to do what I want? In other words, in my service I'm handling the SERVICE_CONTROL_PRESHUTDOWN message. Is there now a SERVICE_CONTROL_PRE_HYBRID_SHUTDOWN message? How do I detect or register to receive a hybrid shutdown message?
|
|
|
|
|
It's possible that what you're looking for is a notification of a power event.
MSDN states:
Quote: dwEventType [in]
If dwControl is SERVICE_CONTROL_POWEREVENT, this parameter can be one of the values specified in the wParam parameter of the WM_POWERBROADCAST message.
Perhaps when the system is going into hybrid shutdown, it sends this control code.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
Thanks, that's a direction I could explore. Ill post
some results here soon.
|
|
|
|
|
Well, I tried using the SystemEvents.PowerModeChanged event, which is the managed analog to what you suggested. I received the Suspend and Resume events just fine but nothing for a power down (even a hybrid one). The mode enumeration is not terribly detailed. It offers Resume (aka wake), Suspend (aka sleep), and some other battery-related modes which are not pertinent to my problem. The return values from the PInvoke you suggested look much the same, so I did not try that.
Also note that I did my experimenting from a Windows Forms program. To do this from a service, MS says it's required to have a message pump in the service, which involves a hidden form and sounds kind of kludgey.
Instead I have this work around: I didn't mention that I also have a user tray app running that monitors the service. On a sleep the system doesn't exit the tray app. On a hybrid shutdown the system does. So in the form close event of tray app I use the CloseReason to find out if it's a non-user exit. If it is I send a custom message to the service to do it's shutdown processing. Sending a custom message is pretty easy:
ServiceController sc = new ServiceController("MyService");
sc.ExecuteCommand(MYSERVICE_QUASI_SHUTDOWN);
...then in the service, the custom command is handled in the OnCustomCommand event handler. MYSERVICE_QUASI_SHUTDOWN is some constant int you pick.
I've read that there's some valid range for it, so as not to step on the future, however I forget what that is just now.
|
|
|
|
|
Hello there,
I'm new in C# language (Actually in programming) , and i try to made an array , and i make search commands to show if the name exist or no .
It works fine , but i need to show me the names that start with the letters i used only .
for example , i used name "Omar" , if i type "m" in the search , it says that "m" letter has been found in the list , but it won't show me the name , because there is no name in the array starts with "m" , and the m they found belong to "Omar" .
so here's my code ,
public static void Main()
{
string[] names = { "Omar", "-232" , "Don" , "Test"};
string theSelected = string.Join(" " , names);
Console.WriteLine("The Avilable names are : " + theSelected);
Console.WriteLine("Which name you need ? ");
point: string Selected = Console.ReadLine();
string[] first = Array.FindAll(names, namess => namess.ToLower().StartsWith(Selected.ToLower(), StringComparison.Ordinal));
int i = 4;
if (!(Selected == "") && !(Selected.StartsWith(" ")))
{
if (theSelected.ToLower().Contains(Selected.ToLower()))
{
Console.WriteLine("The names start with " + Selected.ToUpper() + " is / are : \n" + string.Join("\n", first));
}
else
{
Console.WriteLine("The names start with " + Selected + " is / are : \nNone");
}
}
else
{
Console.WriteLine("The Avilable names are : " + theSelected);
goto point;
}
Console.ReadKey();
}
|
|
|
|
|
You have not made your question clear enough. Please state clearly what you want to happen, and what actually happens instead.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I need the search found only the first letter of the names
like
{"Omar" , "Don" , "232"} when i type "o" on the console , it will show me "Omar" , if i type "q" , it show me "None" , but when i type "m" , it show me an empty line , i used string.Contains method , and it will give me all letters in array , but it only show me the names if i use the first letter , and if i use a letter that is 2nd or 3rd on any name in the array , it will show me an empty line.
so i need the search gives me the name when i type the first letter of the name , otherwise , it show me "None" .
|
|
|
|
|
You can use Linq to do this easily:
using Linq;
private string matchName(string toMatch, string[] source)
{
var match = source.FirstOrDefault(name => name.StartsWith(toMatch));
return (match == null) ? "None" : match;
} The 'FirstOrDefault extension method will return 'null if no match is found; the 'First method would throw an error if no match was found.
I suggest you experiment by adding a boolean flag to the input parameters of the method, and then, based on the flag's value, returning either the first match, or all matches.
«I'm asked why doesn't C# implement feature X all the time. The answer's always the same: because no one ever designed, specified, implemented, tested, documented, shipped that feature. All six of those things are necessary to make a feature happen. They all cost huge amounts of time, effort and money.» Eric Lippert, Microsoft, 2009
|
|
|
|
|
You should try to avoid using goto - it makes your code harder to follow. There are almost always simpler ways to do what you want - for example:
string Selected = Console.ReadLine();
while (Selected == "" || Selected.StartsWith(" "))
{
Console.WriteLine("The Available names are : " + theSelected);
Selected = Console.ReadLine();
}
There's no need to call .ToLower() on the strings to do a case-insensitive comparison; just pass StringComparison.OrdinalIgnoreCase to the StartsWith method:
string[] first = Array.FindAll(names, name => name.StartsWith(Selected, StringComparison.OrdinalIgnoreCase));
Once you've found the matching names, you don't need to test whether the theSelected string contains the entered value; just test whether Array.FindAll returned any values:
if (first.Length != 0)
{
}
else
{
}
You should also consider giving your variables better names, and using camel case for local variable names.
string[] names = { "Omar", "-232" , "Don" , "Test" };
string joinedNames = string.Join(" ", names);
Console.WriteLine("The available names are : {0}", joinedNames);
Console.WriteLine("Which name do you need ? ");
string selected = Console.ReadLine();
while (string.IsNullOrEmpty(selected) || selected.StartsWith(" "))
{
Console.WriteLine("The available names are : {0}", joinedNames);
selected = Console.ReadLine();
}
string[] matchingNames = Array.FindAll(names, name => name.StartsWith(selected, StringComparison.OrdinalIgnoreCase));
Console.WriteLine("The names which start with {0} is / are :", selected.ToUpper());
if (matchingNames.Length != 0)
{
Console.WriteLine(string.Join(Environment.NewLine, matchingNames));
}
else
{
Console.WriteLine("None");
}
Console.ReadKey();
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
I guess you want restart the selection when it isn't found.
Just check the "first"'s lenght to confirm you found or not.
You can change if statement to this one.
if (!(Selected == "") && !(Selected.StartsWith(" ")) && first.Length > 0)
|
|
|
|
|
I need to bind a TCP-client to a specific IP-address and port. The Socket.Bind() method seems to be the way to do this. But I stumble over a problem when I try to bind and connect to the same local and remote end points.
This is what I do:
1) The TCP-client binds to the local endpoint: 172.168.0.10:20001.
2) The TCP-client connects to the remote endpoint: 172.168.0.18:10001.
3) The TCP-client send a request to the TCP-server.
4) Wait some arbitrary time so the TCP-server can respond.
5) The TCP-client receives the respond from the TCP-server.
6) The TCP-client calls the Shutdown and Close methods.
This works, one time.
If I immediately after step 6 start all over from step 1; my applications throws an SocketException at step 2.
The SocketException says:
ErrorCode: 10048
SocketErrorCode: AddressAlreadyInUse
Message: Only one usage of each socket address (protocol/network address/port) is normally permitted 172.168.0.18:10002
MSDN about ErrorCode 10048[^]
Some other information
* I cannot keep the connection with the TCP-server open, this is why I always close after I have received something.
* What I make of it; is that I don't seem to close/shutdown/terminate the socket properly at step 6 for the particular local endpoint.
* If I change the local endpoint's port to 20002 I can restart the sequence without any problems. This works only once as well.
* I have also tried the SetSocketOption with the ResuseAddress enum, but that don't seem to solve the issue.
Any suggestions?
My code:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IPEndPoint local1 = new IPEndPoint(IPAddress.Parse("172.168.0.10"), 20001);
IPEndPoint local2 = new IPEndPoint(IPAddress.Parse("172.168.0.10"), 20002);
IPEndPoint remote = new IPEndPoint(IPAddress.Parse("172.168.0.18"), 10002);
byte[] request = new byte[] { 0x10, 0x7B, 0xFE, 0x79, 0x16 };
Test(local1, remote, request);
Test(local1, remote, request);
Test(local2, remote, request);
}
static void Test(IPEndPoint local, IPEndPoint remote, byte[] request)
{
byte[] response = new byte[0];
TcpClient tcp = new TcpClient();
NetworkStream stream = null;
try
{
tcp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
tcp.Client.Bind(local);
tcp.Connect(remote);
stream = tcp.GetStream();
stream.Write(request, 0, request.Length);
Thread.Sleep(500);
response = new byte[tcp.Available];
stream.Read(response, 0, response.Length);
}
catch (SocketException soe)
{
Console.WriteLine(soe.ErrorCode);
Console.WriteLine(soe.SocketErrorCode);
Console.WriteLine(soe.Message);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
if (tcp.Connected)
{
tcp.Client.Shutdown(SocketShutdown.Both);
}
tcp.Close();
if (stream != null)
{
stream.Close();
}
}
Console.WriteLine("Received: {0} byte(s)", response.Length);
}
}
}
|
|
|
|
|
The client does not need to bind to an address/port, it just needs to create a socket that will connect to the server port.
|
|
|
|
|
Dear Mr Richard, I specific wrote:
"I need to bind a TCP-client to a specific IP-address and port".
Your replay is just meaningless. I know that in most cases the client don't need to bind. But I have a reason where I need it.
|
|
|
|
|
Mc_Topaz wrote: Your replay is just meaningless. As is yours. If you need the client to bind to a specific address then you should explain what you are trying to achieve in proper detail, rather than making stupid comments.
|
|
|
|
|
It was not meant to be a stupid comment when I replied to you. I tried to be polite and make sure you had understood my initial purpose correctly. However I thought your comment was rude since you didn't reflect any further on my question.
But anyway, now I have explained why I need this.
|
|
|
|
|
Mc_Topaz wrote: I tried to be polite
Then I suggest that in future you try a little harder?
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
Down vote countered.
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
|
|
|
|
|
|
Ok!
I see to be needed to explain why I need this.
On the computer running the TCP-client there are several network cards. One specific network card is connected to a LAN. On that LAN there are a bunch of M-Bus gateways (IP-devices). All M-Bus gateway have a bunch of M-Bus meters connected to itself using a kind of serial interface.
The programming running the TCP-client must request all M-Bus meters separately.
To request a specific M-Bus meter is done with providing the meter's unique address in the application layer.
So the TCP-client sends the request to 255.255.255.255:10001. The gateways are configured to listen on port 10001 and send the request further to the M-Bus meters.
That M-Bus meter that correspond to the actual unique address will replay back to it's master.
The M-Bus gateway now only need to send back the replay to the TCP client. In the gateway's configuration there is possible to specify what port the client will receive data on.
So I thought by specifying port 20001 in the gateways and binding to 20001 on the client this should work.
I didn't use the broadcast IP-address in my example because I wanted to keep the example simple.
modified 1-Feb-15 12:55pm.
|
|
|
|
|
Have you tried SocketOptionName.DontLinger ? Basically, when a socket closes, it enters a TIME_WAIT state and lingers for about 4 minutes. DontLinger tells it to miss this stage out and close immediately.
|
|
|
|
|
Thanks Pete but that didn't work.
I tried:
tcp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
tcp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
I still gets the same error
I assume this can also be handled with the TcpClient.LingerState property?
So tcp.LingerState = new LingerOption(true, 1); should just keep the socket open 1ms after I call the Close method?
This didn't work either. Any other suggestions?
|
|
|
|
|
Hmmm, this is bizarre. This code has worked fine for me in the past. Ok, have you typed in netstat -n -a when the connection closes? Use that to see what state that port is at.
|
|
|
|
|
Nice feature. I didn't know that was possible.
I saw that the Local1's IP-address and Port was in state "TimeWait" before and after the call to close.
If it's not is to much to ask: Can you modify my example code as you should have wrote it. Including any SetSocketOptions you feel are necessary?
Thanks for the support Pete!
|
|
|
|
|
Wrap up both your NetworkStream and TcpClient code within a using block[^]. I've encountered problems like this myself when working with sockets or ports and fixed my issues by simply using "using" statements. This has always fixed my open port problem by properly closing the port when I'm finished with it.
Otherwise you have to do a bunch of garbage collection calls and the like to force .NET to do what it will do for you if you simply let it. Let the objects manage themselves by wrapping them up within the simple "using" statement construct. Right now you are fighting .NET by trying to over manage what .NET wishes to manage for you.
Don't fight the using statement, embrace it.
Later....
|
|
|
|
|