Selenium C#保存WhatsApp Web会话失败:仍需重复扫码
Hey there, I see you're trying to persist your WhatsApp Web session using ChromeDriver so you don't have to scan the QR code every time, and you've already added the --user-data-dir argument—but it's still not working. Let's break down what might be going wrong and fix it, using your current setup (Chrome 74 + Selenium WebDriver 3.141.0) as a base.
Common Issues Causing Repeated QR Scans
First, let's diagnose why your current code isn't holding the session:
- Permissions or Path Problems: The folder you're using for
FolderPathToStoreSessionmight not have proper read/write permissions, or you're using a relative path instead of an absolute one (Chrome needs a full path to save session data reliably). - Lingering Chrome Processes: Even after calling
driver.Quit()andDispose(), background Chrome processes might still be running, locking the session directory so the next instance can't load the saved data. - Inadequate Waiting Logic: Hardcoded
Thread.Sleepcalls don't account for varying load times—WhatsApp might not finish loading the session before you close the driver, leading to incomplete session saves. - Missing Chrome Arguments: Beyond
--user-data-dir, there are a few extra flags that help Chrome load saved sessions consistently without resetting to a fresh state.
Step-by-Step Fixes
Let's address each issue with modified code and best practices:
1. Ensure Valid Session Directory
Use an absolute path to a folder your app has full access to (avoid system-protected folders like C:\Windows). For example:
string sessionFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "WhatsAppChromeSession"); // Create the folder if it doesn't exist if (!Directory.Exists(sessionFolder)) Directory.CreateDirectory(sessionFolder);
2. Add Critical Chrome Arguments
Add these flags to your ChromeOptions to prevent Chrome from resetting the session:
options.AddArgument("--no-first-run"); // Skips the first-run setup wizard options.AddArgument("--disable-extensions"); // Disables extensions that might interfere with session data options.AddArgument("--profile-directory=Default"); // Ensures we use the default profile in your session folder
3. Properly Clean Up Chrome Processes
Create a helper method to ensure all Chrome processes are terminated after use—this prevents locked session files:
private static void CleanupChromeResources(ChromeDriver driver, ChromeDriverService service) { if (driver != null) { driver.Close(); driver.Quit(); driver.Dispose(); } // Kill the specific ChromeDriver process if (service != null && service.ProcessId != -1) { try { Process.GetProcessById(service.ProcessId).Kill(); } catch { /* Ignore if process already exited */ } } // Kill any remaining Chrome processes to free the session folder foreach (var chromeProcess in Process.GetProcessesByName("chrome")) { try { if (!chromeProcess.HasExited) { chromeProcess.Kill(); chromeProcess.WaitForExit(5000); } } catch { /* Ignore errors for processes that can't be killed */ } } }
4. Optimize Session Save/Load Logic
Replace hardcoded sleeps with explicit waits to ensure WhatsApp fully loads before closing the driver. This guarantees session data is saved properly.
Optimized OpenNewChrome (First-Time QR Scan)
public static int OpenNewChrome(string Website, int TimeToWaitInMinutes, string FolderPathToStoreSession) { ChromeOptions options = null; ChromeDriver driver = null; ChromeDriverService cService = null; try { int processId = -1; var waitTimeout = TimeSpan.FromMinutes(TimeToWaitInMinutes); cService = ChromeDriverService.CreateDefaultService(); cService.HideCommandPromptWindow = true; options = new ChromeOptions(); // Use absolute path for session directory options.AddArgument($"--user-data-dir={Path.GetFullPath(FolderPathToStoreSession)}"); options.AddArgument("--no-first-run"); options.AddArgument("--disable-extensions"); options.AddArgument("--profile-directory=Default"); driver = new ChromeDriver(cService, options, waitTimeout); processId = cService.ProcessId; driver.Navigate().GoToUrl(Website); // Wait for the QR code to appear so the user can scan it new WebDriverWait(driver, TimeSpan.FromSeconds(10)).Until( d => d.FindElement(By.CssSelector("div[data-ref]")) // WhatsApp's QR code container ); FRM_MSG confirmationDialog = new FRM_MSG(); DialogResult scanResult = confirmationDialog.ShowDLG( "", "Did you successfully scan the QR code?", FRM_MSG.MSGIcon.Question, FRM_MSG.BTNS.Two, new string[] { "Yes, Finish", "Can't Scan" } ); // If scan succeeded, wait for WhatsApp's main chat interface to load (ensures session is saved) if (scanResult == DialogResult.Yes) { new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until( d => d.FindElement(By.Id("pane-side")) // WhatsApp's chat list panel ); } // Clean up all Chrome resources CleanupChromeResources(driver, cService); return scanResult == DialogResult.Yes ? processId : -1; } catch (Exception ex) { CleanupChromeResources(driver, cService); throw ex; } }
Optimized OpenOldChrome (Restore Saved Session)
public static int OpenOldChrome(string Website, int TimeToWaitInMinutes, string FolderPathToStoreSession) { ChromeOptions options = null; ChromeDriver driver = null; ChromeDriverService cService = null; try { int processId = -1; var waitTimeout = TimeSpan.FromMinutes(TimeToWaitInMinutes); cService = ChromeDriverService.CreateDefaultService(); cService.HideCommandPromptWindow = true; options = new ChromeOptions(); options.AddArgument($"--user-data-dir={Path.GetFullPath(FolderPathToStoreSession)}"); options.AddArgument("--no-first-run"); options.AddArgument("--disable-extensions"); options.AddArgument("--profile-directory=Default"); driver = new ChromeDriver(cService, options, waitTimeout); processId = cService.ProcessId; driver.Navigate().GoToUrl(Website); // Wait for the main chat interface to confirm session is restored try { new WebDriverWait(driver, TimeSpan.FromSeconds(30)).Until( d => d.FindElement(By.Id("pane-side")) ); MessageBox.Show("Session restored successfully!"); } catch (WebDriverTimeoutException) { MessageBox.Show("Session not found—you may need to scan the QR code again."); } FRM_MSG exitDialog = new FRM_MSG(); DialogResult exitResult = exitDialog.ShowDLG( "", "Do you want to exit?", FRM_MSG.MSGIcon.Question, FRM_MSG.BTNS.Two, new string[] { "Yes", "No" } ); CleanupChromeResources(driver, cService); return exitResult == DialogResult.Yes ? processId : -1; } catch (Exception ex) { CleanupChromeResources(driver, cService); throw ex; } }
Final Notes
- Version Lock: Keep Chrome 74 and WebDriver 3.141.0 matched—updating Chrome without updating WebDriver will break compatibility and session persistence.
- Unique Session Folders: If you're managing multiple WhatsApp accounts, use a separate folder for each to avoid session conflicts.
- Disable Auto-Updates: Turn off Chrome's automatic updates to prevent unexpected version changes that could invalidate your saved session.
内容的提问来源于stack exchange,提问作者Fath Bakri

