Process.Start can't access roblox protocol - c#

I'm trying to launch roblox from c#, but it seems it cannot find the roblox-protocol.
I tried the code I use in windows run and it did find, but once I try it with Process.Start it says the file could not be found.
public static string LaunchRoblox(string authTicket)
{
Random rnd = new Random();
long browserTrackerId = 55393295400 + rnd.Next(1, 100);
TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
int launchTime = (int)t.TotalSeconds * 1000;
string url = $#"roblox-player:1+launchmode:play+gameinfo:{authTicket}+launchtime:{launchTime}+placelauncherurl:https://assetgame.roblox.com/game/PlaceLauncher.ashx?request=RequestGame&browserTrackerId=" + browserTrackerId + "&placeId=185655149&isPlayTogetherGame=false+browsertrackerid:" + browserTrackerId + "+robloxLocale:en_us+gameLocale:en_us";
return url;
}
static void Main(string[] args)
{
Program.x_crsf_token = GetXCSRFToken();
Console.Write("Sucessfully obtained X-CRSF-Token: " + Program.x_crsf_token);
Console.WriteLine("");
string AuthTicket = GetAuthTicket();
Console.Write("Sucessfully obtained AuthTicket: " + AuthTicket);
Console.WriteLine("");
string joiner = LaunchRoblox(AuthTicket);
Console.Write("Trying to launch roblox with:" + joiner);
Console.WriteLine("");
var game = Process.Start(joiner);
game.WaitForExit();
}
This is the error I get

What you do works in .NET Framework. But your error message shows that you are using .NET 6.0. For any .NET Core and later you would need to do something like:
var psi = new ProcessStartInfo(joiner)
{
UseShellExecute = true
};
var game = Process.Start(psi);

Related

System.Drawing.pdb not included (serializing images with NumSharp)

good day!
i have a situation while trying to process several images in a batch using c#, NumSharp and an onnx model
See an extract code below:
var modelPath = #"Resources/model_20221026.onnx";
var outputColumnNames = new[] { "dense_4" };
var inputColumnNames = new[] { "input_5" };
var mlContext = new MLContext();
var pipeline = mlContext.Transforms.ApplyOnnxModel(outputColumnNames, inputColumnNames, modelPath);
var img0 = Bitmap.FromFile(path, true);
var content = ResizeImage(img0, 512, 512);
img0.Dispose();
var data0 = content.ToNDArray(flat: false, copy: false);
var dataNP = np.array(data0).astype(NPTypeCode.Single).flatten().ToArray<float>();
content.Dispose();
var input = new Input { Data = dataNP };
var dataView = mlContext.Data.LoadFromEnumerable(new[] { input });
var transformedValues = pipeline.Fit(dataView).Transform(dataView);
var output = mlContext.Data.CreateEnumerable<Output>(transformedValues, reuseRowObject: false);
float[] probabilities = output.Single().Data;
float defect = (float)Math.Round(100 * probabilities[0], 2);
float nodefect = (float)Math.Round(100 * probabilities[1], 2);
string[] NameImg = path.Split('\\');
Logger.Info("------------ID: "
+ " " + NameImg[NameImg.Length - 1]
+ " - Defect: " + defect + "%"
+ " - NoDefect: " + nodefect + "%");
It will do it once, sometimes twice, but then, it will crash. The application will crash suddently, and won't write in logs anything if i try to catch any argument error.
If i try in debug mode i get this error:
Any idea is very welcome,
thanks!
I tried in:
Debug mode
Disposing contents
Instead of opening a file with Bitmap.FromFile, i tried to stream the content
I try catching arguments exceptions and exceptions in general

How to print only datalabel out of whole scandata?

I am a new bee to C# programming. I have a zebra bar code scanner. I made a C# code according to the software user manual. I am able to print the scandata. However this data consist of all the information about the scanner. It has serial number,module number,GUID,datatype and datalabel.
This datalabel is the information about the bar code. I am interested in this datalabel only. I need to develop further code using this datalabel.
How can I print only the datalabel?.
Here I am attaching my code. Thank you.
namespace ConsoleApp_scandata
{
class Program
{
//declare the core scanner class
static CCoreScannerClass cCoreScannerClass;
static void Main(string[] args)
{
cCoreScannerClass = new CoreScanner.CCoreScannerClass();
//CALL OPEN API
short[] scannerTypes = new short[1]; //scanner types intrested in
scannerTypes[0] = 1; // set all scanner types to 1
short numberOfScannerTypes = 1; // size of the scanner type array
int status; // Extend API return code
cCoreScannerClass.Open(0, scannerTypes, numberOfScannerTypes, out status);
if (status == 0)
Console.WriteLine("CoreScanner API OPEN");
else
Console.WriteLine("CoreScanner API CLOSED");
// Lists all scanners connected to the host computer.
// will return nothing
short numberOfScanners;
int[] connectedScannerIDList = new int[255];
string outXML;
cCoreScannerClass.GetScanners(out numberOfScanners, connectedScannerIDList, out outXML, out status);
//below does not work because string is an xml file and is never NULL
Console.WriteLine(outXML);
// Console.WriteLine(outXML.ToString());
cCoreScannerClass.BarcodeEvent += new _ICoreScannerEvents_BarcodeEventEventHandler(OnBarcodeEvent);
int opcode = 1001;
string inXML = "<inArgs>" +
"<cmdArgs>" +
"<arg-int>1</arg-int>" +
"<arg-int>1</arg-int>" +
"</cmdArgs>" +
"</inArgs>";
cCoreScannerClass.ExecCommand(opcode, ref inXML, out outXML, out status);
opcode = 2011;
inXML = "<inArgs>" +
"<scannerID>1</scannerID>" +
"</inArgs>";
cCoreScannerClass.ExecCommand(opcode, ref inXML, out outXML, out status);
while (true)
{
Console.Read();
}
}
private static void OnBarcodeEvent(short eventType, ref string pscanData)
{
Console.WriteLine("Scannner Event! Scan Data: " + pscanData);
}
}
}
Load pscanData in the XmlDocumentand your are ready to go, just copy this code:
private static void OnBarcodeEvent(short eventType, ref string pscanData)
{
Console.WriteLine("Scannner Event! Scan Data: " + pscanData);
XmlDocument xmlDoc = new XmlDocument();
//xmlDoc.LoadXml(pscanData); //You should use this line as far as your XML tags are correct
xmlDoc.LoadXml("<scandata>" +
"<modeldata>" +
"099909" +
"</modeldata>" +
"<datalabel>" +
"0x68 0x74 0x74" +
"</datalabel>" +
"</scandata>"); //I use this harcoded XML because I don't have your pscanData, just delete this line and uncoment the one above
XmlNodeList datalabel = xmlDoc.GetElementsByTagName("datalabel");
XmlNode allInDataLabel = datalabel.Item(0);
string whatDatalabelContains = allInDataLabel.InnerText;
Console.WriteLine("Datalabel: " + ToText(whatDatalabelContains));
}
Edit: Hex to text
private static string ToText(string yourHex)
{
StringBuilder sb = new StringBuilder();
string[] dataArr = yourHex.Split(new char[] { ' ' });
for (int i = 0; i < dataArr.Length; i++)
{
sb.Append(Char.ConvertFromUtf32(Convert.ToInt32(dataArr[i], 16)));
}
return sb.ToString();
}

Serializing a manually written code

I am having a problem receiving files from the client. Someone suggested that I should use binary serialization to send and receive messages in stream. Can you give me ideas on how I should serialize this? I just learned about serialization not long ago so I am quite confused on how I should associate it with my program.
This is the client that 'should' be serialize
public void sendthedata()
{
if (!_timer.Enabled) // If timer is not running send data and start refresh interval
{
SendData();
_timer.Enabled = true;
}
else // Stop timer to prevent further refreshing
{
_timer.Enabled = false;
}
}
private List<int> listedProcesses = new List<int>();
private void SendData()
{
String processID = "";
String processName = "";
String processPath = "";
String processFileName = "";
String processMachinename = "";
listBox1.BeginUpdate();
try
{
piis = GetAllProcessInfos();
for (int i = 0; i < piis.Count; i++)
{
try
{
if (!listedProcesses.Contains(piis[i].Id)) //placed this on a list to avoid redundancy
{
listedProcesses.Add(piis[i].Id);
processID = piis[i].Id.ToString();
processName = piis[i].Name.ToString();
processPath = piis[i].Path.ToString();
processFileName = piis[i].FileName.ToString();
processMachinename = piis[i].Machinename.ToString();
output.Text += "\n\nSENT DATA : \n\t" + processFileName + "\n\t" + processMachinename + "\n\t" + processID + "\n\t" + processName + "\n\t" + processPath + "\n";
}
}
catch (Exception ex)
{
wait.Abort();
output.Text += "Error..... " + ex.StackTrace;
}
NetworkStream ns = tcpclnt.GetStream();
String data = "";
data = "--++" + processFileName + " " + processMachinename + " " + processID + " " + processPath;
if (ns.CanWrite)
{
byte[] bf = new ASCIIEncoding().GetBytes(data);
ns.Write(bf, 0, bf.Length);
ns.Flush();
}
}
}
finally
{
listBox1.EndUpdate();
}
}
And deserializing in the server
private void recieveData()
{
NetworkStream nStream = tcpClient.GetStream();
ASCIIEncoding ascii = null;
while (!stopRecieving)
{
if (nStream.CanRead)
{
byte[] buffer = new byte[1024];
nStream.Read(buffer, 0, buffer.Length);
ascii = new ASCIIEncoding();
recvDt = ascii.GetString(buffer);
/*Received message checks if it has +##+ then the ip is disconnected*/
bool f = false;
f = recvDt.Contains("+##+");
if (f)
{
string d = "+##+";
recvDt = recvDt.TrimStart(d.ToCharArray());
clientDis();
stopRecieving = true;
}
//else if (recvDt.Contains("^^"))
//{
// new Transmit_File().transfer_file(file, ipselected);
//}
/* ++-- shutsdown/restrt/logoff/abort*/
else if (recvDt.Contains("++--"))
{
string d = "++--";
recvDt = recvDt.TrimStart(d.ToCharArray());
this.Invoke(new rcvData(addToOutput));
clientDis();
}
/*--++ Normal msg*/
else if (recvDt.Contains("--++"))
{
string d = "--++";
recvDt = recvDt.TrimStart(d.ToCharArray());
this.Invoke(new rcvData(addToOutput));
}
}
Thread.Sleep(1000);
}
}
public void addToOutput()
{
if (recvDt != null && recvDt != "")
{
output.Text += "\n Received Data : " + recvDt;
recvDt = null;
}
}
Thank you.
There are a couple of rules to follow when serialising a piece of data.
It's easy to convert data to bytes, but consider how to reconstruct the data on the other side. Assume that the server can't have any knowledge on what you sended.
In your serialiser you just convert a couple of strings into a byte[] and send it over. Example:
string x = "abcdef";
string y = "ghijk";
var bytes = Encoding.Ascii.GetBytes(x + y);
the server receives: "abcdefghijk";
Is it possible for the server to determine and reconstruct strings x and y?
Since the server has no knowledge of the length of either x and y: no.
There are ways to solve this:
Use fixed length fields. In my example x should always be 6 chars and y should always be 5 chars in length. decoding on the server then becomes as trivial as
string x = data.Substring(0, 6)
string y = data.Substring(6, 5)
Use delimiters between the fields. If you are familiar with cvs, the ',' splits the fields. This however has it drawbacks, how to handle a ',' somewhere in a string? The data send over would be like "abcdef,ghijk"
Send the size of each field before the content of the field.
A naive approach just to clarify: string x would be send as '6abcdef' and y as '5ghijk'
Doing all this things by hand can get really hairy and is something that I would consider only if really needed.
I would resort to existing frameworks that do an excellent job on this subject:
Json.net
protobuf ported by Jon skeet
In this case I would first create a class to define the data send to the server instead of a bunch of strings:
class ProcessInfo{
public string ProcessID {get;set;}
public string ProcessName {get;set;}
public string ProcessPath {get;set;}
public string ProcessFileName {get;set;}
public string ProcessMachinename {get;set;}
};
the using Json to serialise this:
var procinfo = new ProcessInfo{
ProcessId = "1",
...
};
var serialised = JsonConvert.SerializeObject(procinfo);
var bytes = Encoding.Utf8.GetBytes(serialised);
ns.Write(bytes, 0, bytes.Length);
And restore it on the server just by:
var procInfo = JsonConvert.DeserializeObject<ProcessInfo>(json);

get network computer System.Environment.TickCount

I've been searching to find out how to get a remote PC's System.Environment.TickCount.
Using this simple code gets the info I want from my local PC but I can't work out how to get the same info for each PC in our domain network. I want to run this from our server.
TimeSpan t = TimeSpan.FromMilliseconds(System.Environment.TickCount);
MessageBox.Show(t.Days.ToString() + "days, " + t.Hours.ToString() + "hrs & " + t.Minutes.ToString() + "mins.");
I've got this code to get all computer names in the network:
public List<String> ListNetworkComputers()
{
List<String> _ComputerNames = new List<String>();
String _ComputerSchema = "Computer";
System.DirectoryServices.DirectoryEntry _WinNTDirectoryEntries = new System.DirectoryServices.DirectoryEntry("WinNT:");
foreach (System.DirectoryServices.DirectoryEntry _AvailDomains in _WinNTDirectoryEntries.Children)
{
foreach (System.DirectoryServices.DirectoryEntry _PCNameEntry in _AvailDomains.Children)
{
if (_PCNameEntry.SchemaClassName.ToLower().Contains(_ComputerSchema.ToLower()))
{
_ComputerNames.Add(_PCNameEntry.Name);
}
}
}
return _ComputerNames;
}
How can I use this info to get the System.Environment.TickCount from each PC?
I've tried PsExec.exe but I've really got no clue how to get it to work for me. I tried this but it doesn't work:
var list = ListNetworkComputers();
foreach (var pc in list)
{
string output = "";
using (var process = new System.Diagnostics.Process())
{
process.StartInfo.FileName = #"C:\PsExec.exe";
process.StartInfo.Arguments = #"\\" + pc + " cmd /c echo " + "System.Environment.TickCount";
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
output = process.StandardOutput.ReadToEnd();
}
int count = 0;
Int32.TryParse(output, out count);
TimeSpan ts = TimeSpan.FromMilliseconds(count);
MessageBox.Show(pc + ": " + ts.Days.ToString() + "days, " + ts.Hours.ToString() + "hrs & " + ts.Minutes.ToString() + "mins.");
}
Instead of using "cmd.exe", maybe you can use PowerShell? If so, it's a simple command to print that property: [System.Environment]::TickCount
I needed to do the same thing: get a remote PC's System.Environment.TickCount.
I came up with this solution (using Windows Management Instrumentation or WMI LocalDateTime - LastBootUpTime), but it's not 100% accurate compared to Environment.TickCount (see code comment below).
So I checked for other solutions online. Turns out #HansPassant suggested the same thing. For my use case, the +/-100 ticks discrepancy shouldn't matter.
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;
using System;
using System.Linq;
using System.Security;
namespace TickCountTest
{
class Program
{
/// <summary>
/// Print the system TickCount (converted from Win32_OperatingSystem LocalDateTime - LastBootUpTime properties).
/// Why? Because this technique can be used to get TickCount from a Remote machine.
/// </summary>
public static void Main(string[] args)
{
var tickCount = GetRemoteMachineTickCount("REMOTEMACHINENAME");
if (!tickCount.HasValue)
{
throw new NullReferenceException("GetRemoteMachineTickCount() response was null.");
}
Console.WriteLine($"TickCount: {tickCount}");
Console.ReadKey();
}
/// <summary>
/// Retrieves the duration (TickCount) since the system was last started from a remote machine.
/// </summary>
/// <param name="computerName">Name of computer on network to retrieve tickcount for</param>
/// <returns>WMI Win32_OperatingSystem LocalDateTime - LastBootUpTime (ticks)</returns>
private static int? GetRemoteMachineTickCount(string computerName)
{
string namespaceName = #"root\cimv2";
string queryDialect = "WQL";
DComSessionOptions SessionOptions = new DComSessionOptions();
SessionOptions.Impersonation = ImpersonationType.Impersonate;
var baseLineTickCount = Environment.TickCount; // Note: to determine discrepancy
CimSession session = CimSession.Create(computerName, SessionOptions);
string query = "SELECT * FROM Win32_OperatingSystem";
var cimInstances = session.QueryInstances(namespaceName, queryDialect, query);
if (cimInstances.Any())
{
var cimInstance = cimInstances.First();
var lastBootUpTime = Convert.ToDateTime(cimInstance.CimInstanceProperties["LastBootUpTime"].Value);
var localDateTime = Convert.ToDateTime(cimInstance.CimInstanceProperties["LocalDateTime"].Value);
var timeSpan = localDateTime - lastBootUpTime;
var tickCount = Convert.ToInt32(timeSpan.TotalMilliseconds);
var discrepancy = tickCount - baseLineTickCount; // Note: discrepancy about +/- 100 ticks
return tickCount;
}
return null;
}
}
}

How to keep logs in C#?

This is a WinForm written in C#.
Lets say I'm generating a random named text file in my selected directory. When the button is clicked teh first time, i write the data contained in the textboxes into that text file. If the user wants to do the same thing with different data in the textboxes then the click on the button should write the new data into the text file without losing the old data. It's like keeping logs, is this possible?
My code is like:
private readonly Random setere = new Random();
private const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
private string RandomString()
{
char[] buffer = new char[5];
for (int i = 0; i < 5; i++)
{
buffer[i] = chars[setere.Next(chars.Length)];
}
return new string(buffer);
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult dia = MessageBox.Show("Wanna continue?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dia == DialogResult.Yes)
{
StreamWriter wFile = new StreamWriter("C:\\Users\\Ece\\Documents\\Testings\\" + RandomString() + ".txt");
wFile.WriteLine("Name Surname:" + text1.Text + text2.Text);
wFile.WriteLine("Other:" + text3.Text + text4.Text);
wFile.WriteLine("Money:" + textBox1.Text + " TL.");
wFile.WriteLine("*************************************");
wFile.Close();
}
else
{
return;
}
}
You can append to the text in the file.
See
File.AppendText
using (StreamWriter sw = File.AppendText(pathofFile))
{
sw.WriteLine("This");
sw.WriteLine("is Extra");
sw.WriteLine("Text");
}
where pathofFile is the path to the file to append to.
Have a look at using something like this:
StreamWriter fw = new StreamWriter(#"C:\Logs\MyFile.txt",true);
fw.WriteLine("Some Message" + Environment.Newline);
fw.Flush();
fw.Close();
Hope that helps. See MSDN StreamWriter for more information
Updated: Removed old example
Also if you are trying to create a unique file you can use Path.GetRandomFileName()
Again from the MSDN Books:
The GetRandomFileName method returns a
cryptographically strong, random
string that can be used as either a
folder name or a file name.
UPDATED: Added a Logger class example below
Add a new class to your project and add the following lines (this is 3.0 type syntax so you may have to adjust if creating a 2.0 version)
using System;
using System.IO;
namespace LogProvider
{
//
// Example Logger Class
//
public class Logging
{
public static string LogDir { get; set; }
public static string LogFile { get; set; }
private static readonly Random setere = new Random();
private const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
public Logging() {
LogDir = null;
LogFile = null;
}
public static string RandomFileName()
{
char[] buffer = new char[5];
for (int i = 0; i < 5; i++)
{
buffer[i] = chars[setere.Next(chars.Length)];
}
return new string(buffer);
}
public static void AddLog(String msg)
{
String tstamp = Convert.ToString(DateTime.Now.Day) + "/" +
Convert.ToString(DateTime.Now.Month) + "/" +
Convert.ToString(DateTime.Now.Year) + " " +
Convert.ToString(DateTime.Now.Hour) + ":" +
Convert.ToString(DateTime.Now.Minute) + ":" +
Convert.ToString(DateTime.Now.Second);
if(LogDir == null || LogFile == null)
{
throw new ArgumentException("Null arguments supplied");
}
String logFile = LogDir + "\\" + LogFile;
String rmsg = tstamp + "," + msg;
StreamWriter sw = new StreamWriter(logFile, true);
sw.WriteLine(rmsg);
sw.Flush();
sw.Close();
}
}
}
Add this to your forms onload event
LogProvider.Logging.LogDir = "C:\\Users\\Ece\\Documents\\Testings";
LogProvider.Logging.LogFile = LogProvider.Logging.RandomFileName();
Now adjust your button click event to be like the following:
DialogResult dia = MessageBox.Show("Wanna continue?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dia == DialogResult.Yes)
{
StringBuilder logMsg = new StringBuilder();
logMsg.Append("Name Surname:" + text1.Text + text2.Text + Environment.NewLine);
logMsg.Append("Other:" + text3.Text + text4.Text + Environment.NewLine);
logMsg.Append("Money:" + textBox1.Text + " TL." + Environment.NewLine);
logMsg.Append("*************************************" + Environment.NewLine);
LogProvider.Logging.AddLog(logMsg.ToString());
} else
{
return;
}
Now you should only create one file for the entire time that application is running and will log to that one file every time you click your button.
You might want to take a look at log4net and the RollingFileAppender
Sure. Just open the file for appending with something like System.IO.File.AppendText

Categories