MS Edge chromium uses a starter process - pid

I am launching msEdge via kernal32.CreateProcess, the process launches but when I try to interact with the initial process it has exited and a new process is running. I have coded to deal with this but I have code in the wild that is affected by this new behavior and fails to interact with the process as it looks like its exited...
This behaviour first appeared in msEdge update 89.0.774.57 but a colleague has seen it happening after downgrading to 86.0.622.56
Looking for help in how to stop msEdge from starting in this way, I assume its some config option I'm missing...
Sample code (appologies for the VB!):
Sub Main()
Dim creationFlags As Integer = CreationFlagsLocal.NORMAL_PRIORITY_CLASS Or CreationFlagsLocal.DETACHED_PROCESS
startupInfo.cb = Marshal.SizeOf(startupInfo)
Dim path = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe"
CreateProcess(Nothing, path, Nothing, Nothing, False, creationFlags, IntPtr.Zero, Nothing, startupInfo, processInfo)
Console.WriteLine("The processID from CreateProcess was: " & processInfo.dwProcessId)
Console.WriteLine("GetRunningEdgeProcessID() returns " & GetRunningEdgeProcessID())
Dim originalPidExists = Process.GetProcesses().Any(Function(x) x.Id = processInfo.dwProcessId)
Console.WriteLine($"PID {processInfo.dwProcessId} still exists? {originalPidExists}")
End Sub
Code that gets the running process after the initial process exits:
Function GetRunningEdgeProcessID() As Integer
Dim edgeProcesses = Process.GetProcessesByName("msedge")
Dim mainProcess = edgeProcesses.FirstOrDefault(Function(x) Not String.IsNullOrEmpty(x.MainWindowTitle))
If mainProcess IsNot Nothing Then Return mainProcess.Id
Return -1
End Function
Import of CreateProcess:
<DllImport("kernel32.dll", CharSet:=CharSet.Unicode, SetLastError:=True)>
Function CreateProcess(ByVal lpApplicationName As String,
ByVal lpCommandLine As String, ByRef lpProcessAttributes As SECURITY_ATTRIBUTES,
ByRef lpThreadAttributes As SECURITY_ATTRIBUTES, ByVal bInheritHandles As Boolean,
ByVal dwCreationFlags As Integer, ByVal lpEnvironment As IntPtr, ByVal lpCurrentDirectory As String,
<[In]()> ByRef lpStartupInfo As STARTUPINFO,
<[Out]()> ByRef lpProcessInformation As PROCESS_INFORMATION) As Boolean
End Function

It turns out that the process that was launching msEdge was elevated and edge does not want to run elevated, so it relaunches itself in the normal user context. There is a flag that allows edge to run in elevated mode that resolves the original issue.
Also, the issue can be caused by use of the Start-Up Boost feature that MS has recently remote disabled as it was causing issues like this edge://flags#edge-de-elevate-on-launch
Further reading:


Upload Image using VB.Net and SQL Server

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim command As New SqlCommand("insert into rent(Image,Status)values(#Image,#Status)", connection)
Dim ms As New MemoryStream
PictureBox1.Image.Save("ms", PictureBox1.Image.RawFormat)
command.Parameters.Add("#Image", SqlDbType.VarChar).Value = ms.ToArray
command.Parameters.Add("#Status", SqlDbType.VarChar).Value = TextBox5.Text
If command.ExecuteNonQuery = 1 Then
MessageBox.Show("Successfully uploaded")
MessageBox.Show("Not uploaded")
End If
End Sub
I'm trying to upload an image into my SQL Server using Visual Studio; everything is working except when I click the upload button, I keep getting the following error:
I tried every possible solution and no luck, I tried enabling the tcp and changing the ip even in SQL Server.
The error you get means that you can't connect to SQL Server.
Make sure your connection string is correct, and you don't have a firewall blocking the connection between the computer that runs the code and the computer that hosts SQL Server.
However, once you sort the connection error, you still have a few problems with your code.
change PictureBox1.Image.Save("ms", PictureBox1.Image.RawFormat)
to PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
to save the image into the memory stream.
Change command.Parameters.Add("#Image", SqlDbType.VarChar).Value = ms.ToArray
to command.Parameters.Add("#Image", SqlDbType.VarBinary).Value = ms.ToArray
because memoryStream.ToArray returns a byte array, not a string.
make sure the Image column in your table is, in fact, VarBinary.
SqlCommand, SqlConnection and MemoryStream all implements the IDisposable interface, therefor you should use all of them as local variable inside the using statement. Your code suggest you are using a class level SqlConnecion instance. That should be changed.
All communication with the database should be inside a try...catch block, since too many things you can't control can go wrong (network disconnected, for instance).
Your code should look more like this:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim RowsEffected as int = 0
Using Dim connection As NewSqlConnection(ConnectionString
Using Dim command As New SqlCommand("insert into rent(Image,Status)values(#Image,#Status)", connection)
Using Dim ms As New MemoryStream
PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
command.Parameters.Add("#Image", SqlDbType.VarBinary).Value = ms.ToArray
command.Parameters.Add("#Status", SqlDbType.VarChar).Value = TextBox5.Text
RowsEffected = command.ExecuteNonQuery()
End Try
Catch Exception ex
MessageBox.Show("Failed to upload image:"& VbCrLf & ex.Message)
End Catch
End Using
End Using
End Using
If RowsEffected = 1 Then
MessageBox.Show("Successfully uploaded")
MessageBox.Show("Not uploaded")
End If
End Sub

Connecting Visual Basic to local database

I've got a question regarding Visual Basic's local database. So far I've managed to: 1. Create a Local Database, named it Database1 2. Create a table with values (username, password, year/section, secretquestion, secretanswer) 3. Create a dataset in form1(to get form2's entries) 4. Create a registration form in form 2( 5 labels/textboxes to get username,password,year/section,secretquestion,secretanswer)
Here's my current code for Form2:
Public Class Form2
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection("Data Source=C:\Users\Bounty Hounds\AppData\Local\Temporary Projects\WindowsApplication1\Database1.sdf")
Dim cmd As New System.Data.SqlClient.SqlCommand
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = "INSERT Username (user) Password (pass) Year/Section (yns) SecretQuestion (sq) SecretAnswer (sa)"
cmd.Connection = sqlConnection1
End Sub
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Dim user As String
user = TextBox1.Text
End Sub
Private Sub TextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox2.TextChanged
Dim pass As String
pass = TextBox2.Text
End Sub
Private Sub TextBox3_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox3.TextChanged
Dim yns As String
yns = TextBox3.Text
End Sub
Private Sub TextBox4_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox4.TextChanged
Dim sq As String
sq = TextBox4.Text
End Sub
Private Sub TextBox5_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox5.TextChanged
Dim sa As String
sa = TextBox5.Text
End Sub
End Class
But as soon as I click the register button it gives me an error and points at the sqlConnection1.Open() line, the error is: "A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections."
In the Database Explorer I see my Database1.sdf with an X on its icon(the small yellow cylinder) and checked that its state is closed, so I tried opening it by right clicking it, then modify connection, placed the Database1.sdf path in the Database, inputted my password and pressed ok. At that point I see my Database1.sdf state go "Open" but when I ran my application the state went to "Closed" again (btw I see this state thing by right clicking my Database1.sdf in the Solution Explorer).
This text below has little to no connection with my code above and I just wanted your opinions on what is the best approach to the software I want to create so if you only want to help me on my code which I greatly appreaciate, you can stop reading the paragraphs below but if you do take time to consider reading it, It would mean alot to me. THANKS
The connection of a visual basic form and a database is the first step of what I really want to do, what my main goal is a File Storage system between two PCs which I'll increase once I figured out those 2 PCs.
To reach that goal I tried to divide each problems so I can address them accordingly and eventually finishing the entire software.
Establish a connection between 2 PCs (which I've done by setting PC2's dns server with PC1's ip address).
Connect a visual basic form (which in my case is a registration form) with a database for storing user accounts.
Make every registration create a folder for the certain users that registered. The folders created will be the storage of their files (this idea is really vague atm as I don't know how will I do this, AND VERY IMPORTANT PART IS ONLY THE REGISTERED USERS FROM THE DATABASE ONLY HAVE ACCESS TO THE FOLDERS THEY OWN(sorry i'm not shouting, just noting this as I feel this is the hardest part to do)
Implement a disk quota on the folders to limit sizes.
Create a Login system for PC2 to connect to the database of PC1 (Database should verify this and give an error if the infos are incorrect).
Create a Save/Load button for PC2 (I want PC2 to save its myDocuments Folder on PC1's Folder for Storage Files by using the My.Computer.FileSystem.CopyDirectory command. Then load will copy the PC1's Folder and load it into PC2's MyDocuments Folder.
Lastly and the biggest question is that are all these possible to do with Visual Basic? I've tried it with Windows Active Directory using roaming user profiles but I really want to develop my own software.
#Jimmy Smith
Thanks for replying, I've decided to create another database named CCS and my new code for form2 is:
Dim conn As New System.Data.SqlServerCe.SqlCeConnection()
Dim cmd As New System.Data.SqlClient.SqlCommand
conn.ConnectionString = _
"Persist Security Info = False; Data Source = 'C:\Users\Bounty Hounds\Documents\Visual Studio 2010\Projects\WindowsApplication2\WindowsApplication2\CCS.sdf';" & _
"Password = joshua8; File Mode = 'shared read'; "
cmd.CommandType = System.Data.CommandType.Text
cmd.CommandText = "INSERT Username (user) Password (pass) Year/Section (yns) SecretQuestion (sq) SecretAnswer (sa)"
However, It generates a new error:
There is a file sharing violation. A different process might be using the file. [ C:\Users\Bounty Hounds\Documents\Visual Studio 2010\Projects\WindowsApplication2\WindowsApplication2\CCS.sdf ]
You can't connect to SDF files direct without using the Compact Edition library. Unfortunately, it's not installed by default as Microsoft seems to be phasing it out.
Use System.Data.SqlserverCe.SqlCeConnection in place of System.Data.SqlClient.SqlConnection GetProcess Options

I currently have the following code that runs an external Virtual Application(created with Cameyo), when the Run Button is clicked. I also have a Timer that checks ever second to see if the Process(virtual exe program) is still open. In theory the GetProcessByName should find the program listed in the Task Manager right? However it doesn't! I even tried using GetProcessByName to Kill the process (one another button clicked), but the processs is not killed.
Could it be because I virtualized the program that I want GetProcessByName to recognize? Therefore the name of the Task in the Task Manager is not correct?.
The program started: SmartDefrag.virtual.exe
It runs
The Task Manager shows it as SmartDefrag.exe
Use GetProcessByName("SmartDefrag.exe") to Disable Run Button if process SmartDefrag.exe running.
Does not Disable Run Button.
Could I use TITLE OF PROCESS? Or will the PID be the same everytime the process opens? Any other options?
Private Sub SMDFRunAppMainButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles SMDFRunAppMainButton.Click
' LoadingSMDFMainButton.Visibility = Windows.Visibility.Visible
Dim downloadlocation As String = (currentpath & "\1stAidApps\SMDF\SmartDefrag.virtual.exe")
My.Settings.FileLoad = downloadlocation
Try 'Errors on Cancel
dp1Timer = New DispatcherTimer
dp1Timer.Interval = TimeSpan.FromMilliseconds(1000)
AddHandler dp1Timer.Tick, AddressOf TickMe1
fileload = My.Settings.FileLoad
Catch ex As Exception
MessageBox.Show("Failed to launch. Please try again.", "Launch Failed")
End Try
End Sub
Private Sub TickMe1()
Dim p() As Process
p = Process.GetProcessesByName("SmartDefrag.exe")
If p.Count > 0 Then
LoadingSMDFMainButton.Visibility = Windows.Visibility.Hidden
SMDFRunAppMainButton.IsEnabled = False
SMDFRunAppMainButton.IsEnabled = True
End If
End Sub
GetProcessByName doesn't take the full path, but rather the "name" of the process. This will likely need to be GetProcessByName("SmartDefrag").
From the documentation for GetProcessByName:
The process name is a friendly name for the process, such as Outlook, that does not include the .exe extension or the path.

"Impersonated" User Not Propagated To SQL Server 2000

I need to "impersonate" a user in a VB.NET 2008 WinForms application, so that the application can accept the Active Directory login of any user on a PC regardless of who is actually logged in to Windows. I want the application's My.User to be the AD account of the person who logged in to the application. I succeeded in this with the following code:
Private Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As String, ByVal lpszDomain As String, _
ByVal lpszPassword As String, ByVal dwLogonType As Integer, _
ByVal dwLogonProvider As Integer, ByRef phToken As IntPtr) As Boolean
Const LOGON32_PROVIDER_WINNT35 As Long = 1
Const LOGON32_PROVIDER_WINNT40 As Long = 2
Const LOGON32_PROVIDER_WINNT50 As Long = 3
' Influenced from the example at
Public Shared Function Login(ByVal uid As String, ByVal pwd As String) As Boolean
' Get the user's domain name.
Dim domainName As String = My.User.Name.Substring(0, My.User.Name.IndexOf("\"))
' This token is returned by the LogonUser API call (variable is passed ByRef).
Dim token As IntPtr
If LogonUser(uid, domainName, pwd, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token) Then
' Added this line per response to this question:
' If the login succeeds, then impersonate that user by changing CurrentPrincipal.
Dim wi As New Principal.WindowsIdentity(token)
Dim wp As New Principal.WindowsPrincipal(wi)
My.User.CurrentPrincipal = wp
Return True
Return False
End If
End Function
However, the application uses a .DLL with the Data Access Layer which is connecting to SQL Server 2000. It appears that SQL Server, using "Integrated Security=SSPI" in the connection string, is receiving the login of the account logged in to Windows and not the account returned My.User.CurrentPrincipal.Identity, when stepping through the code, in both the WinForms app code and the .DLL's app code.
Both the WinForms app and .DLL code properly recognize My.User.CurrentPrincipal.Identity as the account logged in to the app, not Windows. It's just not propagating to SQL Server. This is evidenced by Stored procedures writing SUSER_SNAME() to a table's column in T-SQL.
Can anyone see what I'm going wrong?
EDIT: I've added the line WindowsIdentity.Impersonate(token) as stated, but now when my .DLL tries to create an SQL Server connection it throws this error:
Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.
You need to call WindowsIdentity.Impersonate();:
If LogonUser(...) Then

Why does my winsock control not function correctly in vb6 within the context of a Form_QueryUnload?

My goal is to have this program send a logout command when the user is logging off or shutting down their pc.
The program is connected to a server application via a tcp socket using a Winsock object. Calling singleSock.SendData "quit" & vbCrLf is simply a way of logging out. I am going to start capturing data with Wireshark, but I'd like to know if I'm trying to do something fundamentally wrong.
Oddly enough, if I set Cancel to True, and allow a timer I have running to do the logout command, then call another unload, it works, however in testing this configuration (different code), this prevents the user from logging out the first time. They have to initiate a logout, it doesn't do anything, then they logout again and my program is gone at that point. Also oddly enough, in Vista the logout goes through after briefly displaying a screen saying my program was preventing the logout. Most of my deployment is on XP, which has the two logouts problem.
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If UnloadMode = vbFormControlMenu Then
Me.WindowState = vbMinimized
Cancel = True
Cancel = False
Cancel = True
End If
tmrSocket.Enabled = False
Sleep (1000)
singleSock.SendData "quit" & vbCrLf
Call pUnSubClass
'If singleSock.state <> sckConnected Then
' singleSock.Close
' tmrSocket.Enabled = False
' LogThis "tmrSocket turned off"
'End If
End If
End Sub
You're not waiting for the Winsock control to actually send the "quit" message. The SendData method is asynchronous: it can return before the data has actually been sent across the network. The data is buffered locally on your machine and sent at some later time by the network driver.
In your case, you are trying to send the "quit" message and then closing the socket almost immediately afterwards. Because SendData is asynchronous, the call might return before the "quit" message has actually been sent to the server, and therefore the code might close the socket before it has a chance to send the message.
It works when you cancel the unloading of the form first and let the timer send the "quit" message because you're giving the socket enough extra time to send the message to the server before the socket is closed. However, I wouldn't count on this always working; it's a coincidence that the extra steps gave the socket enough time to send the message, and it's not guaranteed to always work out that way.
You can fix the problem by waiting for the socket to raise a SendCompleted event after you send the "quit" message and before you close the socket. Below is a basic example. Note that the QueryUnload code is much simpler.
Private m_bSendCompleted As Boolean
Private m_bSocketError As Boolean
Private Sub singleSock_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
'Set error flag so we know if a SendData call failed because of an error'
'A more robust event handler could also store the error information so that'
'it can be properly logged elsewhere'
m_bSocketError = True
End Sub
Private Sub singleSock_SendCompleted()
'Set send completed flag so we know when all our data has been sent to the server'
m_bSendCompleted = True
End Sub
'Helper routine. Use this to send data to the server'
'when you need to make sure that the client sends all the data.'
'It will wait until all the data is sent, or until an error'
'occurs (timeout, connection reset, etc.).'
Private Sub SendMessageAndWait(ByVal sMessage As String)
m_bSendCompleted = False
singleSock.SendData sMessage
singleSock.SendData sMessage
Do Until m_bSendCompleted or m_bSocketError
If m_bSocketError Then
Err.Raise vbObjectError+1024,,"Socket error. Message may not have been sent."
End If
End Sub
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
'This is (almost) all the code needed to properly send the quit message'
'and ensure that it is sent before the socket is closed. The only thing'
'missing is some error-handling (because SendMessageAndWait could raise an error).'
If UnloadMode = vbFormControlMenu Then
Me.WindowState = vbMinimized
Cancel = True
SendMessageAndWait "quit" & vbCrLf
End If
End Sub
You can make the code cleaner by putting the logic to send a message and wait for it to be sent in a separate class. This keeps the private variables and the event handlers in one place, instead of having them litter your main code. It also makes it easier to re-use the code when you have multiple sockets. I called the class SynchronousMessageSender for lack of a better name. This example also has more complete error handling:
Private WithEvents m_Socket As Winsock
Private m_bAttached As Boolean
Private m_bSendCompleted As Boolean
Private m_bSocketError As Boolean
Private Type SocketError
Number As Integer
Description As String
Source As String
HelpFile As String
HelpContext As Long
End Type
Private m_LastSocketError As SocketError
'Call this method first to attach the SynchronousMessageSender to a socket'
Public Sub AttachSocket(ByVal socket As Winsock)
If m_bAttached Then
Err.Raise 5,,"A socket is already associated with this SynchronousMessageSender instance."
End If
If socket Is Nothing Then
Err.Raise 5,,"Argument error. 'socket' cannot be Nothing."
End If
Set m_Socket = socket
End Sub
Private Sub socket_SendCompleted()
m_bSendCompleted = True
End Sub
Private Sub socket_Error(ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
m_bSocketError = True
'Store error information for later use'
'Another option would be to create an Error event for this class'
'and re-raise it here.'
With m_lastSocketError
.Number = Number
.Description = Description
.Source = Source
.HelpFile = HelpFile
.HelpContext = HelpContext
End With
End Sub
'Sends the text in sMessage and does not return'
'until the data is sent or a socket error occurs.'
'If a socket error occurs, this routine will re-raise'
'the error back to the caller.'
Public Sub SendMessage(ByVal sMessage As String)
If Not m_bAttached Then
Err.Raise 5,,"No socket is associated with this SynchronousMessageSender. Call Attach method first."
End If
m_bSendCompleted = False
m_bSocketError = False
m_socket.SendData sMessage & vbCrLf
'Wait until the message is sent or an error occurs'
Do Until m_bSendCompleted Or m_bSocketError
If m_bSocketError Then
End If
End Sub
Private Sub RaiseLastSocketError()
Err.Raise m_lastSocketError.Number, _
m_lastSocketError.Source, _
m_lastSocketError.Description, _
m_lastSocketError.HelpFile, _
End Sub
Example Use
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim sender As New SynchronousMessageSender
'Ignore errors since the application is closing...'
On Error Resume Next
If UnloadMode = vbFormControlMenu Then
Me.WindowState = vbMinimized
Cancel = True
Set sender = New SynchronousMessageSender
sender.AttachSocket singleSock
sender.SendMessage "quit"
End If
End Sub
By using a separate class, now all the necessary code can be placed in the Form_QueryUnload, which keeps things tidier.
Wouldn't is be easier to just go without the QUIT command. In your server code just assume that the closing of a socket does the same thing as receiving a quit.
I addition, one thing you want to watch out for is abrupt shut downs of the client software. For example, a machine that losses power or network connection or a machine that goes into sleep or hibernate mode.
In those cases you should be periodically checking the connection for all of the clients from the server and closing any connections that do not respond to some kind of ping command.