@@ -19,6 +19,7 @@ export class WindowsApplicationManager extends ApplicationManagerBase {
1919 $hooksService : IHooksService ,
2020 $deviceLogProvider : Mobile . IDeviceLogProvider ,
2121 private $childProcess : IChildProcess ,
22+ private _restartLogStream ?: ( ) => Promise < void > ,
2223 ) {
2324 super ( $logger , $hooksService , $deviceLogProvider ) ;
2425 }
@@ -144,43 +145,67 @@ export class WindowsApplicationManager extends ApplicationManagerBase {
144145
145146 /**
146147 * Returns the path of the runtime's trace log for the most recently started app.
147- * For UWP-packaged apps the runtime DLL writes inside the app container's TempState,
148- * not the global system temp directory. Falls back to the system temp path used when
149- * the app is launched as an unpackaged EXE.
148+ * Inside a UWP process, Win32 GetTempPathW() virtualises to AC\Temp (the app
149+ * container's isolated temp folder) — NOT the WinRT TemporaryFolder (TempState).
150+ * Rust's std::env::temp_dir() calls GetTempPathW(), so the DLL writes to AC\Temp.
151+ * Falls back to the system temp path when no PFN is known (unpackaged EXE).
150152 */
151153 public getLogFilePath ( ) : string {
152154 const systemTempLog = path . join ( os . tmpdir ( ) , "ns_trace.log" ) ;
153155 if ( this . _packageFamilyNames . size > 0 ) {
154156 const pfn = this . _packageFamilyNames . values ( ) . next ( ) . value as string ;
155157 const localAppData = process . env . LOCALAPPDATA ;
156158 if ( localAppData && pfn ) {
157- return path . join ( localAppData , "Packages" , pfn , "TempState " , "ns_trace.log" ) ;
159+ return path . join ( localAppData , "Packages" , pfn , "AC" , "Temp ", "ns_trace.log" ) ;
158160 }
159161 }
160162 return systemTempLog ;
161163 }
162164
165+ /**
166+ * Returns the path of the C# crash/exception log written by CrashDiagnostics.
167+ * Lives in LocalState (persistent app data).
168+ * Returns null when no PFN is known (e.g. unpackaged EXE targets).
169+ */
170+ public getCrashLogPath ( ) : string | null {
171+ if ( this . _packageFamilyNames . size > 0 ) {
172+ const pfn = this . _packageFamilyNames . values ( ) . next ( ) . value as string ;
173+ const localAppData = process . env . LOCALAPPDATA ;
174+ if ( localAppData && pfn ) {
175+ return path . join ( localAppData , "Packages" , pfn , "LocalState" , "nativescript-crash.log" ) ;
176+ }
177+ }
178+ return null ;
179+ }
180+
163181 public async startApplication (
164182 appData : Mobile . IStartApplicationData ,
165183 ) : Promise < void > {
166- // Truncate the trace log so the streamer starts from a clean state each run.
167- try {
168- const logPath = this . getLogFilePath ( ) ;
169- fs . writeFileSync ( logPath , "" , "utf8" ) ;
170- } catch { /* ignore — log dir may not exist yet */ }
171-
172184 const exeCandidate =
173185 ( appData . appId && this . _installedExePaths [ appData . appId ] ) ||
174186 ( appData . projectName && this . _installedExePaths [ appData . projectName ] ) ;
187+ const isExe = ! ! ( exeCandidate && fs . existsSync ( exeCandidate ) ) ;
188+
189+ // For UWP, pre-populate the PFN cache before calling getLogFilePath() so
190+ // that the truncation and the subsequent log stream restart both target the
191+ // correct container TempState path instead of the system temp fallback.
192+ if ( ! isExe ) {
193+ await this . _resolvePackageFamilyName ( appData . appId ) ;
194+ }
195+
196+ // Truncate the trace log so the streamer starts from a clean state each run.
197+ try {
198+ fs . writeFileSync ( this . getLogFilePath ( ) , "" , "utf8" ) ;
199+ } catch { /* ignore — log dir may not exist yet */ }
175200
176- if ( exeCandidate && fs . existsSync ( exeCandidate ) ) {
201+ if ( isExe ) {
177202 if ( appData . waitForDebugger ) {
178203 this . $logger . info (
179204 `[Windows] --debug-brk is not supported for EXE targets.` ,
180205 ) ;
181206 }
182207 this . $logger . info ( `[Windows] Launching EXE: ${ exeCandidate } ` ) ;
183- const proc = spawn ( exeCandidate , [ ] , { detached : true , stdio : "ignore" } ) ;
208+ const proc = spawn ( exeCandidate as string , [ ] , { detached : true , stdio : "ignore" } ) ;
184209 proc . unref ( ) ;
185210 this . _runningPid = proc . pid ?? null ;
186211 // Clear stale PID when the process exits so stopApplication falls back to
@@ -190,22 +215,30 @@ export class WindowsApplicationManager extends ApplicationManagerBase {
190215 this . _runningPid = null ;
191216 }
192217 } ) ;
193- return ;
218+ } else {
219+ // PFN already cached from the pre-resolve above; no extra round-trip.
220+ const pfn = this . _packageFamilyNames . get ( appData . appId ) ?? appData . appId ;
221+ if ( appData . waitForDebugger ) {
222+ this . _writeDebugBreakMarker ( pfn ) ;
223+ }
224+ // UWP apps are launched via shell:AppsFolder\<PFN>!<ApplicationId>.
225+ // The ApplicationId comes from the <Application Id="..."> attribute in the manifest.
226+ const appId = "App" ;
227+ this . $logger . info ( `[Windows] Launching UWP: ${ pfn } !${ appId } ` ) ;
228+ const proc = spawn ( "explorer.exe" , [ `shell:AppsFolder\\${ pfn } !${ appId } ` ] , {
229+ detached : true ,
230+ stdio : "ignore" ,
231+ } ) ;
232+ proc . unref ( ) ;
194233 }
195234
196- const pfn = await this . _resolvePackageFamilyName ( appData . appId ) ;
197- if ( appData . waitForDebugger ) {
198- this . _writeDebugBreakMarker ( pfn ) ;
235+ // Restart the log stream so the tailer picks up the correct path (UWP
236+ // container TempState vs. system temp) and resets its offset to 0. Without
237+ // this the tailer keeps the stale offset from device-discovery time and
238+ // skips every log line written after the file was truncated above.
239+ if ( this . _restartLogStream ) {
240+ await this . _restartLogStream ( ) ;
199241 }
200- // UWP apps are launched via shell:AppsFolder\<PFN>!<ApplicationId>.
201- // The ApplicationId comes from the <Application Id="..."> attribute in the manifest.
202- const appId = "App" ;
203- this . $logger . info ( `[Windows] Launching UWP: ${ pfn } !${ appId } ` ) ;
204- const proc = spawn ( "explorer.exe" , [ `shell:AppsFolder\\${ pfn } !${ appId } ` ] , {
205- detached : true ,
206- stdio : "ignore" ,
207- } ) ;
208- proc . unref ( ) ;
209242 }
210243
211244 public async stopApplication (
0 commit comments