Dev Investigation Notes

What to check, in order, when WiFi QR autofill comes back null in a local Windows web app

This is a translated article. Read the original in Korean ↗

This isn't a finished implementation. It's a diagnostic order for figuring out where the null comes from. A local web app (formation) has viewer and reader pages that people open on their phones. On the app's server screen, the goal was for the Node server on the Windows PC to read the current WiFi name and password and fill in the inputs for the connection QR code. The first check returned null from /wifi.

Conclusion

If you get null, check whether the PC running the server is connected to WiFi at that moment before you suspect the code. In this case, the null showed up while WiFi was disconnected and the PC was on a wired connection.

Run the checks below in order, from the same PowerShell or Command Prompt window you start the server from. The commands follow the netsh wlan syntax in Microsoft's docs. The record for this case has no complete commands and no profile-selection code, so none of the commands in this article were run and verified here. Microsoft Learn: netsh wlan

StepCheckPasses whenIf it fails
1netsh wlan show interfacesState is connected and the SSID line has a nameIt's a connection problem. Connect to WiFi and start again from step 1. Don't look at the server code yet
2The server's /wifi responseIt isn't null and the SSID matches the name from step 1Look at the server code that reads the SSID (the command call and output parsing). The output text can vary with the OS language
3PasswordThe response includes the password and it fills the inputRun netsh wlan show profiles to list the saved profiles and see whether the profile name differs from the SSID. Also check whether the server is running as administrator (see "Starting the server as administrator" below). Microsoft's docs say exporting with key=clear requires local administrator rights
4ScreenThe inputs autofill when nothing is saved, and the button reloads the valuesCheck whether an old value left in the browser's localStorage caused autofill to be skipped. In the browser dev tools (F12) → Application → Local Storage, delete the WiFi-related entries for this server's address and refresh

According to the docs, the way to read the password is to export the profile as XML. The format is netsh wlan export profile name="<프로필 이름>" key=clear folder="<출력 폴더>", and the password appears in plaintext in the exported XML's <keyMaterial>. This leaves a plaintext file behind, so point the output folder at a temporary location and delete the file once you've checked it. Pick <프로필 이름> (profile name) from the show profiles list above, and fill in <출력 폴더> (output folder) yourself. The record for this case doesn't show how the server actually picked the profile.

To call the same command from the Node server, run it with child_process and read the output string. Below is a minimal example based on Node's official API. It wasn't run or verified for this article. The output text can vary with the OS language, so adjust the regex to match the output on your own PC.

const { execFileSync } = require('child_process');
const out = execFileSync('netsh', ['wlan', 'show', 'interfaces'], { encoding: 'utf8' });
const m = out.match(/^\s*SSID\s*:\s*(.+)$/m); // The BSSID line doesn't match, since it isn't a line with only whitespace before SSID
const ssid = m ? m[1].trim() : null;         // null if not connected

For the password, run ['wlan','export','profile','name='+ssid,'key=clear','folder='+os.tmpdir()] the same way. Then read the generated XML (Wi-Fi-<프로필 이름>.xml), pull out the <keyMaterial> value, and delete the file.

This record never confirms that the values fill in while connected. The conclusion at the time, "the parsing logic is fine," was reached with no connection, so this article doesn't accept it.

Situation

A local server runs on a Windows PC. The operator screen takes a WiFi name and password as input, stores them in the browser's localStorage, and generates a QR code. The request was to "use the currently connected WiFi as the default." A browser can't read the WiFi password directly, so the plan was for the server to call an OS command and serve the result at /wifi.

Symptom

When the server was started for verification, /wifi returned null. After that, the screen rendered without errors and the "현재 연결된 WiFi 불러오기" (Load currently connected WiFi) button appeared. But nothing reports that real WiFi details were ever filled in.

Cause

The confirmed facts in this case are that netsh reported State: disconnected and that the PC was on a wired connection. That explains why there was no SSID and why the result was null. However, the record contains neither the full netsh output nor the server's parser code. So you can say it was null because there was no connection, but this record doesn't support the conclusion that it works correctly once connected.

Fix

Follow the table in the Conclusion. If the connection is down, connect to WiFi and pass steps 1–4 in order. Only change the server code if step 1 passes and you then get stuck at step 2 or 3. Use the step 2 rule, that the SSID must match step 1, to decide whether the value was read correctly.

Starting the server as administrator

If only the password is empty at step 3, suspect the server process's privileges. In the Start menu, right-click PowerShell (or Command Prompt), choose "관리자 권한으로 실행" (Run as administrator), and start the server from that window as usual. The server has to be started from an administrator window so that netsh running inside it inherits administrator rights. This advice is based on general Windows behavior and wasn't confirmed in the record for this case.

Checking who can reach /wifi

In this design, the /wifi response contains the password in plaintext. The explanation was that only the operator page calls it, but nothing said whether the server blocks direct requests from other devices. Until you've checked the items below, assume any other device on the same network can open it.

The record doesn't show the response JSON shape, how the command is called, or how the XML is parsed.

Bonus — when the camera picks up both QR codes at once

On the same screen, the WiFi QR and the viewer connection QR sat close enough together that the camera captured both. Spreading them apart inside the card wasn't enough, so they were reportedly placed at opposite edges of the screen with width:100vw and space-between. Whether this actually improved scanning on a real phone wasn't confirmed.

Reporter's Notes — "no value" is not the same as "the code is right"

Park Doeun
You know the local web app I'm building, with viewer and reader pages people open on their phones? The server PC's screen shows a WiFi QR for connecting. I'm trying to fill in the name and password automatically, but the server response is null.
Jung Bada
The parsing's wrong. The output text is in Korean, so a regex written for English can't catch it. I'm sure of it.
Jung Haneul
That's a guess. First let's check whether the server PC is even on WiFi right now, and what the command actually prints. If it's connected, Bada might be right. If not, we don't even need to look at the parser.
Park Doeun
But what is the parser parsing? What exactly does netsh give you?
Park Dohyun
It's Windows' network configuration command. Run netsh wlan show interfaces and you get the current wireless adapter's connection state and its SSID, meaning the wireless network name.
Park Doeun
Ran it. State is disconnected. This PC is on a wired connection and WiFi was off.
Jung Bada
Huh? So it's not a regex problem. There was never a name to read in the first place. My diagnosis was wrong.
Jung Haneul
Right, that explains the null. But it doesn't mean "the parsing is fine" yet. We've never run it while connected.
Park Dohyun
Exactly. Getting an empty value when there's no input doesn't prove you get the right value when there is input. So connect to WiFi, send the same request again, and see whether the SSID actually fills in. That settles it.
Park Doeun
The screen loads fine, and the "현재 연결된 WiFi 불러오기" (Load currently connected WiFi) button is there. But seeing the button doesn't mean the password got filled in.
Jung Haneul
How does it read the password, anyway? It's not like it's shown on screen.
Jung Bada
The design exports the profile as XML and reads <keyMaterial>. With the key=clear option, the password goes in as-is. I picked it because it holds up better when the output text is localized.
Park Doeun
As-is? Then that XML file just sits there.
Park Dohyun
That's why whether it gets deleted is something to check. The record doesn't show that step. We can't call something safe when we haven't checked it.
Jung Haneul
Same goes for the response. /wifi carries the password in plaintext. All we have is "only the operator page calls it." We don't know whether it's blocked if another phone opens it directly.
Jung Bada
We can just open the address directly on a viewer phone. If the password shows up, there's no access restriction.
Park Doeun
Then let's set the order of checks: WiFi connection, the SSID from /wifi, whether the password fills in, the on-screen inputs, and last, a direct request from another phone. If a step fails, we don't move on to the next one.
Park Dohyun
Good. The lesson this time is to conclude only as much as the conditions we actually checked. Getting null with no connection doesn't guarantee it works when connected.